在上一節(jié),我們演示了怎么使用jwt鑒權(quán),相信你已經(jīng)掌握了對jwt的基本使用,本節(jié)我們來看一下api服務(wù)中間件怎么使用。
在go-zero中,中間件可以分為路由中間件和全局中間件,路由中間件是指某一些特定路由需要實現(xiàn)中間件邏輯,其和jwt類似,沒有放在jwt:xxx下的路由不會使用中間件功能, 而全局中間件的服務(wù)范圍則是整個服務(wù)。
這里以search服務(wù)為例來演示中間件的使用
$ cd service/search/api
$ vim search.api
type SearchReq struct {}
type SearchReply struct {}
@server(
jwt: Auth
middleware: Example // 路由中間件聲明
)
service search-api {
@handler search
get /search/do (SearchReq) returns (SearchReply)
}
$ goctl api go -api search.api -dir .
etc/search-api.yaml exists, ignored generation
internal/config/config.go exists, ignored generation
search.go exists, ignored generation
internal/svc/servicecontext.go exists, ignored generation
internal/handler/searchhandler.go exists, ignored generation
internal/handler/pinghandler.go exists, ignored generation
internal/logic/searchlogic.go exists, ignored generation
internal/logic/pinglogic.go exists, ignored generation
Done.
生成完后會在internal目錄下多一個middleware的目錄,這里即中間件文件,后續(xù)中間件的實現(xiàn)邏輯也在這里編寫。
$ vim service/search/api/internal/svc/servicecontext.go
type ServiceContext struct {
Config config.Config
Example rest.Middleware
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
Example: middleware.NewExampleMiddleware().Handle,
}
}
$ vim service/search/api/internal/middleware/examplemiddleware.go
package middleware
import "net/http"
type ExampleMiddleware struct {
}
func NewExampleMiddleware() *ExampleMiddleware {
return &ExampleMiddleware{}
}
func (m *ExampleMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// TODO generate middleware implement function, delete after code implementation
// Passthrough to next handler if need
next(w, r)
}
}
{"@timestamp":"2021-02-09T11:32:57.931+08","level":"info","content":"example middle"}
通過rest.Server提供的Use方法即可
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
// 全局中間件
server.Use(func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
logx.Info("global middleware")
next(w, r)
}
})
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}
{"@timestamp":"2021-02-09T11:50:15.388+08","level":"info","content":"global middleware"}
通過閉包的方式把其它服務(wù)傳遞給中間件,示例如下:
// 模擬的其它服務(wù)
type AnotherService struct{}
func (s *AnotherService) GetToken() string {
return stringx.Rand()
}
// 常規(guī)中間件
func middleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("X-Middleware", "static-middleware")
next(w, r)
}
}
// 調(diào)用其它服務(wù)的中間件
func middlewareWithAnotherService(s *AnotherService) rest.Middleware {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("X-Middleware", s.GetToken())
next(w, r)
}
}
}
更多建議: