我似乎不知道如何正确地使用中间件和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
}
,但我得到错误未定义: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
,应该提供一个更好的错误响应)