go-zero 中間件使用

2022-04-21 10:44 更新

中間件使用

在上一節(jié),我們演示了怎么使用jwt鑒權(quán),相信你已經(jīng)掌握了對jwt的基本使用,本節(jié)我們來看一下api服務(wù)中間件怎么使用。

中間件分類

在go-zero中,中間件可以分為路由中間件和全局中間件,路由中間件是指某一些特定路由需要實現(xiàn)中間件邏輯,其和jwt類似,沒有放在jwt:xxx下的路由不會使用中間件功能, 而全局中間件的服務(wù)范圍則是整個服務(wù)。

中間件使用

這里以search服務(wù)為例來演示中間件的使用

路由中間件

  • 重新編寫search.api文件,添加middleware聲明

  $ 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)
  }

  • 重新生成api代碼

  $ 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)邏輯也在這里編寫。

  • 完善資源依賴ServiceContext

 $ 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,
     }
 }

  • 編寫中間件邏輯 這里僅添加一行日志,內(nèi)容example middle,如果服務(wù)運行輸出example middle則代表中間件使用起來了。

  $ 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)
      }
  }

  • 啟動服務(wù)驗證

  {"@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"}

在中間件里調(diào)用其他服務(wù)

通過閉包的方式把其它服務(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)
        }
    }
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號