Middleware

[!TIP] This document is machine-translated by Google. If you find grammatical and semantic errors, and the document description is not clear, please PR

In the previous section, we demonstrated how to use jwt authentication. I believe you have mastered the basic use of jwt. In this section, let’s take a look at how to use api service middleware.

Middleware classification

In go-zero, middleware can be divided into routing middleware and global middleware. Routing middleware refers to certain specific routes that need to implement middleware logic, which is similar to jwt and does not place the routes under jwt:xxx Does not use middleware functions, The service scope of global middleware is the entire service.

Middleware use

Here we take the search service as an example to demonstrate the use of middleware

Routing middleware

  • Rewrite the search.api file and add the middleware declaration
    1. $ cd service/search/cmd/api
    2. $ vim search.api
    1. @server(
    2. jwt: Auth
    3. middleware: Example // Routing middleware declaration
    4. )
    5. service search-api {
    6. @handler search
    7. get /search/do (SearchReq) returns (SearchReply)
    8. }
  • Regenerate the api code
    1. $ goctl api go -api search.api -dir .
    1. etc/search-api.yaml exists, ignored generation
    2. internal/config/config.go exists, ignored generation
    3. search.go exists, ignored generation
    4. internal/svc/servicecontext.go exists, ignored generation
    5. internal/handler/searchhandler.go exists, ignored generation
    6. internal/handler/pinghandler.go exists, ignored generation
    7. internal/logic/searchlogic.go exists, ignored generation
    8. internal/logic/pinglogic.go exists, ignored generation
    9. Done.
    After the generation is completed, there will be an additional middleware directory under the internal directory, which is the middleware file, and the implementation logic of the subsequent middleware is also written here.
  • Improve resource dependency ServiceContext

    1. $ vim service/search/cmd/api/internal/svc/servicecontext.go
    1. type ServiceContext struct {
    2. Config config.Config
    3. Example rest.Middleware
    4. }
    5. func NewServiceContext(c config.Config) *ServiceContext {
    6. return &ServiceContext{
    7. Config: c,
    8. Example: middleware.NewExampleMiddleware().Handle,
    9. }
    10. }
  • Write middleware logic Only one line of log is added here, with the content example middle. If the service runs and outputs example middle, it means that the middleware is in use.

    1. $ vim service/search/cmd/api/internal/middleware/examplemiddleware.go
    1. func (m *ExampleMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
    2. return func(w http.ResponseWriter, r *http.Request) {
    3. logx.Info("example middle")
    4. next(w, r)
    5. }
    6. }
  • Start service verification
    1. {"@timestamp":"2021-02-09T11:32:57.931+08","level":"info","content":"example middle"}

Global middleware

call rest.Server.Use

  1. func main() {
  2. flag.Parse()
  3. var c config.Config
  4. conf.MustLoad(*configFile, &c)
  5. ctx := svc.NewServiceContext(c)
  6. server := rest.MustNewServer(c.RestConf)
  7. defer server.Stop()
  8. // Global middleware
  9. server.Use(func(next http.HandlerFunc) http.HandlerFunc {
  10. return func(w http.ResponseWriter, r *http.Request) {
  11. logx.Info("global middleware")
  12. next(w, r)
  13. }
  14. })
  15. handler.RegisterHandlers(server, ctx)
  16. fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
  17. server.Start()
  18. }
  1. {"@timestamp":"2021-02-09T11:50:15.388+08","level":"info","content":"global middleware"}