使用 Alice 和 HttpRouter 的中间件

Middleware using Alice and HttpRouter

我似乎不知道如何正确地一起使用中间件和 Http Router。

我的代码是:

type appContext struct {
  db *mgo.Database
}

func main(){
  c := appContext{session.DB("db-name")}
  commonHandlers := alice.New(context.ClearHandler, basicAuthHandler)

  router := NewRouter()
  router.Post("/", commonHandlers.ThenFunc(c.final))

  http.ListenAndServe(":5000", router)
}

最终中间件是:

func (c *appContext) final(w http.ResponseWriter, r *http.Request) {
  log.Println("Executing finalHandler")
  w.Write([]byte("TESTING"))
}

但我希望我的 basicAuthHandler 成为 commonHandlers 的一部分。它还需要 context 以便我可以查询数据库。

我试过这个:

func (c *appContext) basicAuthHandler(w http.ResponseWriter, r *http.Request) {
  var app App
  err := c.db.C("apps").Find(bson.M{"id":"abcde"}).One(&app)
  if err != nil {
    panic(err)
  }

  //do something with the app
}

但我收到错误 未定义:basicAuthHandler。我明白为什么我会收到错误,但我不知道如何避免它。我怎样才能将 context 提供给 basicAuthHandler 并且仍然在 Alice 的 commonHandlers 列表中使用它?

您的中间件需要有签名

func(http.Handler) http.Handler

这样您的中间件就可以包装处理程序,而不仅仅是提供最终处理程序。您需要接受 http.Handler,执行任何需要完成的处理,然后在链中的下一个处理程序上调用 ServeHTTP。您的 basicAuthHandler 示例可能如下所示:

func (c *appContext) basicAuthHandler(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        var app App
        err := c.db.C("apps").Find(bson.M{"id": "abcde"}).One(&app)
        if err != nil {
            panic(err)
        }
        h.ServeHTTP(w, r)

    })
}

(尽管您不想 panic 在您的应用中,并且应该提供更好的错误响应)