How to use middlewares when using julienschmidt/httprouter in goLang?

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

How to use middlewares when using julienschmidt/httprouter in goLang?

问题

使用julienschmidt/httprouter时,如何以最佳方式链接中间件?

根据我搜索的结果,http.HandlerFunc只接受形式为func (w ResponseWriter, r *Request)的函数,而httprouter.Handle函数的形式为func (w http.ResponseWriter, r *http.Request, ps httprouter.Params)

如何在不将httprouter.Handle函数转换为http.HandlerFunc的情况下链接中间件?

例如:
我的routes.go文件的形式如下:

  1. router := httprouter.New()
  2. router.POST("/api/user/create", middlewares.EscapeStringsMiddleware(User.CreateUser))
  3. log.Fatal(http.ListenAndServe(":8000", router))

如何为上述路由编写中间件函数?

已尝试的方法:

  1. func EscapeStringsMiddleware(next http.Handler) httprouter.Handle {
  2. return func(response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
  3. err := request.ParseForm()
  4. if err != nil {
  5. panic(err)
  6. }
  7. for key, values := range request.Form {
  8. for i, value := range values {
  9. value = template.HTMLEscapeString(value)
  10. value = template.JSEscapeString(value)
  11. request.Form[key][i] = value
  12. }
  13. }
  14. next.ServeHTTP(response, request)
  15. }
  16. }

获得的错误:

无法将User.CreateUser(类型为func(http.ResponseWriter, *http.Request, httprouter.Params))作为middlewares.EscapeStringsMiddleware的参数类型http.Handler:
func(http.ResponseWriter, *http.Request, httprouter.Params)未实现http.Handler(缺少ServeHTTP方法)

  1. func EscapeStringsMiddleware(next httprouter.Handle) httprouter.Handle {
  2. return func(response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
  3. err := request.ParseForm()
  4. if err != nil {
  5. panic(err)
  6. }
  7. for key, values := range request.Form {
  8. for i, value := range values {
  9. value = template.HTMLEscapeString(value)
  10. value = template.JSEscapeString(value)
  11. request.Form[key][i] = value
  12. }
  13. }
  14. next.ServeHTTP(response, request)
  15. }
  16. }

获得的错误:

next.ServeHTTP未定义(类型httprouter.Handle没有ServeHTTP字段或方法)

另外,如何链接多个中间件?

例如:

  1. router.POST("/api/user/create", middlewares.VerifyCSRF(middlewares.EscapeStringsMiddleware(User.CreateUser)))
英文:

What's the best way to chain middlewares while using julienschmidt/httprouter?

As far as I have googled, http.HandlerFunc accepts functions only in the form func (w ResponseWriter, r *Request) whereas httprouter.Handle functions are of the form func (w http.ResponseWriter, r *http.Request, ps httprouter.Params).

How to I chain middlewares without converting the httprouter.Handle function into http.HandlerFunc?

For example:
My routes.go is of the form,

  1. router := httprouter.New()
  2. router.POST("/api/user/create", middlewares.EscapeStringsMiddleware(User.CreateUser))
  3. log.Fatal(http.ListenAndServe(":8000", router))

How do I write middleware functions for the above mentioned route?

Already tried methods:

1.

  1. func EscapeStringsMiddleware(next http.Handler) httprouter.Handle {
  2. return func (response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
  3. err := request.ParseForm()
  4. if err != nil {
  5. panic(err)
  6. }
  7. for key, values := range request.Form {
  8. for i, value := range values {
  9. value = template.HTMLEscapeString(value)
  10. value = template.JSEscapeString(value)
  11. request.Form[key][i] = value
  12. }
  13. }
  14. next.ServeHTTP(response, request)
  15. }
  16. }

Error obtained:

  1. cannot use User.CreateUser (type func(http.ResponseWriter, *http.Request, httprouter.Params)) as type http.Handler in argument to middlewares.EscapeStringsMiddleware:
  2. func(http.ResponseWriter, *http.Request, httprouter.Params) does not implement http.Handler (missing ServeHTTP method)

2.

  1. func EscapeStringsMiddleware(next httprouter.Handle) httprouter.Handle {
  2. return func (response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
  3. err := request.ParseForm()
  4. if err != nil {
  5. panic(err)
  6. }
  7. for key, values := range request.Form {
  8. for i, value := range values {
  9. value = template.HTMLEscapeString(value)
  10. value = template.JSEscapeString(value)
  11. request.Form[key][i] = value
  12. }
  13. }
  14. next.ServeHTTP(response, request)
  15. }
  16. }

Error obtained:

  1. next.ServeHTTP undefined (type httprouter.Handle has no field or method ServeHTTP)

Also how do I chain multiple middleware?

For example,

  1. router.POST("/api/user/create", middlewares.VerifyCSRF(middlewares.EscapeStringsMiddleware(User.CreateUser)))

答案1

得分: 17

这个问题与你的中间件处理程序无关。你之所以出错是因为User.CreateUser不是http.Handler类型。

尝试使用以下模式:

重要的部分是返回一个http.Handler,并使用http.HandlerFunc包装func(w http.ResponseWriter, r *http.Request)

  1. func Handler() http.Handler {
  2. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  3. // do stuff
  4. })
  5. }

根据你的反馈:

httprouter.Handle没有实现ServeHTTP。它直接被调用。例如:next(w, r, ps)

以下是中间件处理程序的示例:

  1. // 无需 "github.com/julienschmidt/httprouter" 的中间件
  2. func StdToStdMiddleware(next http.Handler) http.Handler {
  3. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  4. // do stuff
  5. next.ServeHTTP(w, r)
  6. })
  7. }
  8. // 用于返回 "github.com/julienschmidt/httprouter" Handle 的标准处理程序的中间件
  9. func StdToJulienMiddleware(next http.Handler) httprouter.Handle {
  10. return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
  11. // do stuff
  12. next.ServeHTTP(w, r)
  13. }
  14. }
  15. // 纯粹的 "github.com/julienschmidt/httprouter" 中间件
  16. func JulienToJulienMiddleware(next httprouter.Handle) httprouter.Handle {
  17. return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
  18. // do stuff
  19. next(w, r, ps)
  20. }
  21. }
  22. func JulienHandler() httprouter.Handle {
  23. return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
  24. // do stuff
  25. }
  26. }
  27. func StdHandler() http.Handler {
  28. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  29. // do stuff
  30. })
  31. }
  32. func main() {
  33. router := httprouter.New()
  34. router.POST("/api/user/create", StdToJulienMiddleware(StdHandler()))
  35. router.GET("/api/user/create", JulienToJulienMiddleware(JulienHandler()))
  36. log.Fatal(http.ListenAndServe(":8000", router))
  37. }

希望对你有帮助!

英文:

This issue is not with your middleware handler. You are getting errs because User.CreateUser is not of type http.Handler.

Try this pattern :

The important bit is to return a http.Handler and wrap func(w http.ResponseWriter, r *http.Request) with http.HandlerFunc.

  1. func Handler() http.Handler {
  2. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  3. // do stuff
  4. })
  5. }

go source :

  1. // The HandlerFunc type is an adapter to allow the use of
  2. // ordinary functions as HTTP handlers. If f is a function
  3. // with the appropriate signature, HandlerFunc(f) is a
  4. // Handler that calls f.
  5. type HandlerFunc func(ResponseWriter, *Request)
  6. // ServeHTTP calls f(w, r).
  7. func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
  8. f(w, r)
  9. }

Based on your feedback:

httprouter.Handle does not implement ServeHTTP. It is called directly. For example : next(w, r, ps)

Below you will find examples of middleware handlers.

  1. // Middleware without "github.com/julienschmidt/httprouter"
  2. func StdToStdMiddleware(next http.Handler) http.Handler {
  3. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  4. // do stuff
  5. next.ServeHTTP(w, r)
  6. })
  7. }
  8. // Middleware for a standard handler returning a "github.com/julienschmidt/httprouter" Handle
  9. func StdToJulienMiddleware(next http.Handler) httprouter.Handle {
  10. return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
  11. // do stuff
  12. next.ServeHTTP(w, r)
  13. }
  14. }
  15. // Pure "github.com/julienschmidt/httprouter" middleware
  16. func JulienToJulienMiddleware(next httprouter.Handle) httprouter.Handle {
  17. return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
  18. // do stuff
  19. next(w, r, ps)
  20. }
  21. }
  22. func JulienHandler() httprouter.Handle {
  23. return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
  24. // do stuff
  25. }
  26. }
  27. func StdHandler() http.Handler {
  28. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  29. // do stuff
  30. })
  31. }
  32. func main() {
  33. router := httprouter.New()
  34. router.POST("/api/user/create", StdToJulienMiddleware(StdHandler()))
  35. router.GET("/api/user/create", JulienToJulienMiddleware(JulienHandler()))
  36. log.Fatal(http.ListenAndServe(":8000", router))
  37. }

答案2

得分: 0

https://github.com/cnvrtly/adaptr 库中,适配器也被添加到链式请求中间件函数中。

  1. func compatibleHandler(h http.Handler, httprParamsCtxKey interface{}) httprouter.Handle {
  2. return toHttpRouterHandle(h, httprParamsCtxKey)
  3. }
  4. func toHttpRouterHandle(h http.Handler, httprParamsCtxKey interface{}) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
  5. return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
  6. if httprParamsCtxKey != nil {
  7. r = SetCtxValue(r, httprParamsCtxKey, p)
  8. }
  9. h.ServeHTTP(w, r)
  10. }
  11. }

如果你正在寻找如何定义路由的示例/想法,请参考 https://github.com/cnvrtly/golang-appengine-seed

英文:

From https://github.com/cnvrtly/adaptr lib where adapters are also added to chain request middleware functions.

  1. func compatibleHandler(h http.Handler, httprParamsCtxKey interface{}) httprouter.Handle {
  2. return toHttpRouterHandle(h, httprParamsCtxKey)
  3. }
  4. func toHttpRouterHandle(h http.Handler, httprParamsCtxKey interface{}) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
  5. return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
  6. if httprParamsCtxKey != nil {
  7. r = SetCtxValue(r, httprParamsCtxKey, p)
  8. }
  9. h.ServeHTTP(w, r)
  10. }
  11. }

If you are looking for example/idea how to define routes: https://github.com/cnvrtly/golang-appengine-seed

huangapple
  • 本文由 发表于 2017年5月14日 21:31:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/43964461.html
匿名

发表评论

匿名网友

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

确定