英文:
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文件的形式如下:
router := httprouter.New()
router.POST("/api/user/create", middlewares.EscapeStringsMiddleware(User.CreateUser))
log.Fatal(http.ListenAndServe(":8000", router))
如何为上述路由编写中间件函数?
已尝试的方法:
func EscapeStringsMiddleware(next http.Handler) httprouter.Handle {
return func(response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
err := request.ParseForm()
if err != nil {
panic(err)
}
for key, values := range request.Form {
for i, value := range values {
value = template.HTMLEscapeString(value)
value = template.JSEscapeString(value)
request.Form[key][i] = value
}
}
next.ServeHTTP(response, request)
}
}
获得的错误:
无法将User.CreateUser(类型为func(http.ResponseWriter, *http.Request, httprouter.Params))作为middlewares.EscapeStringsMiddleware的参数类型http.Handler:
func(http.ResponseWriter, *http.Request, httprouter.Params)未实现http.Handler(缺少ServeHTTP方法)
func EscapeStringsMiddleware(next httprouter.Handle) httprouter.Handle {
return func(response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
err := request.ParseForm()
if err != nil {
panic(err)
}
for key, values := range request.Form {
for i, value := range values {
value = template.HTMLEscapeString(value)
value = template.JSEscapeString(value)
request.Form[key][i] = value
}
}
next.ServeHTTP(response, request)
}
}
获得的错误:
next.ServeHTTP未定义(类型httprouter.Handle没有ServeHTTP字段或方法)
另外,如何链接多个中间件?
例如:
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,
router := httprouter.New()
router.POST("/api/user/create", middlewares.EscapeStringsMiddleware(User.CreateUser))
log.Fatal(http.ListenAndServe(":8000", router))
How do I write middleware functions for the above mentioned route?
Already tried methods:
1.
func EscapeStringsMiddleware(next http.Handler) httprouter.Handle {
return func (response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
err := request.ParseForm()
if err != nil {
panic(err)
}
for key, values := range request.Form {
for i, value := range values {
value = template.HTMLEscapeString(value)
value = template.JSEscapeString(value)
request.Form[key][i] = value
}
}
next.ServeHTTP(response, request)
}
}
Error obtained:
cannot use User.CreateUser (type func(http.ResponseWriter, *http.Request, httprouter.Params)) as type http.Handler in argument to middlewares.EscapeStringsMiddleware:
func(http.ResponseWriter, *http.Request, httprouter.Params) does not implement http.Handler (missing ServeHTTP method)
2.
func EscapeStringsMiddleware(next httprouter.Handle) httprouter.Handle {
return func (response http.ResponseWriter, request *http.Request, ps httprouter.Params) {
err := request.ParseForm()
if err != nil {
panic(err)
}
for key, values := range request.Form {
for i, value := range values {
value = template.HTMLEscapeString(value)
value = template.JSEscapeString(value)
request.Form[key][i] = value
}
}
next.ServeHTTP(response, request)
}
}
Error obtained:
next.ServeHTTP undefined (type httprouter.Handle has no field or method ServeHTTP)
Also how do I chain multiple middleware?
For example,
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)
。
func Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do stuff
})
}
根据你的反馈:
httprouter.Handle
没有实现ServeHTTP
。它直接被调用。例如:next(w, r, ps)
以下是中间件处理程序的示例:
// 无需 "github.com/julienschmidt/httprouter" 的中间件
func StdToStdMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do stuff
next.ServeHTTP(w, r)
})
}
// 用于返回 "github.com/julienschmidt/httprouter" Handle 的标准处理程序的中间件
func StdToJulienMiddleware(next http.Handler) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// do stuff
next.ServeHTTP(w, r)
}
}
// 纯粹的 "github.com/julienschmidt/httprouter" 中间件
func JulienToJulienMiddleware(next httprouter.Handle) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// do stuff
next(w, r, ps)
}
}
func JulienHandler() httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// do stuff
}
}
func StdHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do stuff
})
}
func main() {
router := httprouter.New()
router.POST("/api/user/create", StdToJulienMiddleware(StdHandler()))
router.GET("/api/user/create", JulienToJulienMiddleware(JulienHandler()))
log.Fatal(http.ListenAndServe(":8000", router))
}
希望对你有帮助!
英文:
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
.
func Handler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do stuff
})
}
go source :
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
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.
// Middleware without "github.com/julienschmidt/httprouter"
func StdToStdMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do stuff
next.ServeHTTP(w, r)
})
}
// Middleware for a standard handler returning a "github.com/julienschmidt/httprouter" Handle
func StdToJulienMiddleware(next http.Handler) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// do stuff
next.ServeHTTP(w, r)
}
}
// Pure "github.com/julienschmidt/httprouter" middleware
func JulienToJulienMiddleware(next httprouter.Handle) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// do stuff
next(w, r, ps)
}
}
func JulienHandler() httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
// do stuff
}
}
func StdHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// do stuff
})
}
func main() {
router := httprouter.New()
router.POST("/api/user/create", StdToJulienMiddleware(StdHandler()))
router.GET("/api/user/create", JulienToJulienMiddleware(JulienHandler()))
log.Fatal(http.ListenAndServe(":8000", router))
}
答案2
得分: 0
从 https://github.com/cnvrtly/adaptr 库中,适配器也被添加到链式请求中间件函数中。
func compatibleHandler(h http.Handler, httprParamsCtxKey interface{}) httprouter.Handle {
return toHttpRouterHandle(h, httprParamsCtxKey)
}
func toHttpRouterHandle(h http.Handler, httprParamsCtxKey interface{}) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
if httprParamsCtxKey != nil {
r = SetCtxValue(r, httprParamsCtxKey, p)
}
h.ServeHTTP(w, r)
}
}
如果你正在寻找如何定义路由的示例/想法,请参考 https://github.com/cnvrtly/golang-appengine-seed
英文:
From https://github.com/cnvrtly/adaptr lib where adapters are also added to chain request middleware functions.
func compatibleHandler(h http.Handler, httprParamsCtxKey interface{}) httprouter.Handle {
return toHttpRouterHandle(h, httprParamsCtxKey)
}
func toHttpRouterHandle(h http.Handler, httprParamsCtxKey interface{}) func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
if httprParamsCtxKey != nil {
r = SetCtxValue(r, httprParamsCtxKey, p)
}
h.ServeHTTP(w, r)
}
}
If you are looking for example/idea how to define routes: https://github.com/cnvrtly/golang-appengine-seed
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论