使用Alice和HttpRouter的中间件

huangapple go评论77阅读模式
英文:

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)

huangapple
  • 本文由 发表于 2015年5月20日 00:59:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/30331759.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定