英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论