使用Alice和HttpRouter的中间件

时间:2015-05-19 16:59:58

标签: go middleware go-alice

我似乎无法一起研究如何正确使用中间件和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"))
}

但我希望我的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
}

但我收到错误 undefined:basicAuthHandler 。我理解为什么我会收到错误,但我不知道如何避免错误。我如何向context提供basicAuthHandler并仍然在Alice的commonHandlers列表中使用它?

1 个答案:

答案 0 :(得分:1)

您的中间件需要签名

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,并且应该提供更好的错误响应)