使用Alice和HttpRouter的中间件



我似乎不知道如何正确地使用中间件和Http路由器。

我的代码是:
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"))
}

但我希望我的basicAuthHandlercommonHandlers的一部分。它还需要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,应该提供一个更好的错误响应)

最新更新