英文:
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)
}
final 中间件是:
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)
}
// 对 app 进行操作
}
但是我得到了错误 undefined: basicAuthHandler。我理解为什么会出现这个错误,但我不知道如何避免它。我该如何在 basicAuthHandler
中提供 context
并将其仍然用于 Alice 的 commonHandlers
列表中?
英文:
I can't seem to work out how to use middleware and Http Router properly together.
My code is:
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)
}
The final middleware is:
func (c *appContext) final(w http.ResponseWriter, r *http.Request) {
log.Println("Executing finalHandler")
w.Write([]byte("TESTING"))
}
but I want my basicAuthHandler
to be part of the commonHandlers. It also needs the context
so that I can query the db.
I have tried this:
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
}
but I get the error undefined: basicAuthHandler. I understand why I'm getting the error but I don't know how to avoid it. How can I provide the context
to the basicAuthHandler
and still use it in the commonHandlers
list for Alice?
答案1
得分: 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
,而应该提供更好的错误响应)
英文:
Your middleware needs to have the signature
func(http.Handler) http.Handler
This way your middleware is wrapping handlers, not just providing a final handler. You need to accept an http.Handler
, do whatever processing needs to be done, and call ServeHTTP
on the next handler in the chain. Your basicAuthHandler example could look like this:
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)
})
}
(though you don't want to panic
in your app, and should provide a better error response)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论