中间件机制

Handler 是tango的中间件。在tango中,几乎所有的事情都由中间件来完成。撰写一个你自己的中间件非常简单,并且我们鼓励您只加载需要的中间件。

tango的中间件只需要符合以下接口即可。

  1. type Handler interface {
  2. Handle(*tango.Context)
  3. }

同时,tango也提供了tango.HandlerFunc,以方便你将一个函数包装为中间件。比如:

  1. func MyHandler() tango.HandlerFunc {
  2. return func(ctx *tango.Context) {
  3. fmt.Println("this is my first tango handler")
  4. ctx.Next()
  5. }
  6. }
  7. t := tango.Classic()
  8. t.Use(MyHandler())
  9. t.Run()

正常的形式也可以是:

  1. type HelloHandler struct {}
  2. func (HelloHandler) Handle(ctx *tango.Context) {
  3. fmt.Println("before")
  4. ctx.Next()
  5. fmt.Println("after")
  6. }
  7. t := tango.Classic()
  8. t.Use(new(HelloHandler))
  9. t.Run()

当然,你可以直接将一个包含tango.Context指针的函数作为中间件,如:

  1. tg.Use(func(ctx *tango.Context){
  2. fmt.Println("before")
  3. ctx.Next()
  4. fmt.Println("after")
  5. })

为了和标准库兼容,tango通过UseHandler支持http.Handler作为中间件,如:

  1. tg.UseHandler(http.Handler(func(resp http.ResponseWriter, req *http.Request) {
  2. }))

老的中间件会被action被匹配之前进行调用。

Call stack

以下是中间件的调用顺序图:

  1. tango.ServeHttp
  2. |--Handler1
  3. |--Handler2
  4. |-- ...HandlerN
  5. |---Action(If matched)
  6. ...HandlerN--|
  7. Handler2 ----|
  8. Handler1--|
  9. (end)--|

在中间件中,您的中间件代码可以在Next()被调用之前或之后执行,Next表示执行下一个中间件或Action被执行(如果url匹配的话)。如果不调用Next,那么当前请求将会被立即停止,之后的所有代码将不会被执行。