英文:
Nest Functions From Slice
问题
我正在构建一个支持各种中间件函数的 Go Web 应用程序,用于处理路由。我尽量使用 net/http
,想知道如何在不使用像 negroni 这样的中间件库的情况下实现这一点。
基本上,我想做的是能够提供一个中间件函数的切片,比如一个用于记录日志,一个用于检查有效的 JWT,最后是处理请求的处理程序。
我可以使用 negroni 简单地实现这一点,定义如下结构体:
// Route ..
type Route struct {
Method string
Path string
Middleware []negroni.Handler
Handler http.HandlerFunc
}
然后像这样定义一个路由:
var commonRoutes = []Route{
{
Method: "GET",
Path: "/info",
Middleware: []negroni.Handler{negroni.HandlerFunc(middleware.CheckCache), negroni.HandlerFunc(middleware.Authenticated), negroni.NewLogger()},
Handler: handlers.APIInfo,
},
}
最后,当我启动服务器时,我导入路由列表并进行注册,像这样:
for _, r := range routes {
handler := append(r.Middleware, negroni.Wrap(r.Handler))
router.Handle(r.Path, negroni.New(handler...)).Methods(r.Method)
}
这样可以完美地工作。
有没有办法只使用标准的 net/http
签名和定义中间件处理程序的方式来实现这一点呢?
谢谢
英文:
I am building a Go web application that supports various middleware functions when handling routing. I'm trying to stick to net/http
as much as possible and was wondering how I might accomplish this without using middleware libraries like negroni.
Essentially what I would like to do is to be able to provide a slice of middleware functions, say one for logging, one for checking for a valid JWT, and then finally the handler to handle the request.
I am able to do this with negroni fairly simply by defining the following struct:
// Route ..
type Route struct {
Method string
Path string
Middleware []negroni.Handler
Handler http.HandlerFunc
}
and then defining a route like:
var commonRoutes = []Route{
{
Method: "GET",
Path: "/info",
Middleware: []negroni.Handler{negroni.HandlerFunc(middleware.CheckCache), negroni.HandlerFunc(middleware.Authenticated), negroni.NewLogger()},
Handler: handlers.APIInfo,
},
}
Finally when I boot up my server, I import the list of routes and register them like so:
for _, r := range routes {
handler := append(r.Middleware, negroni.Wrap(r.Handler))
router.Handle(r.Path, negroni.New(handler...)).Methods(r.Method)
}
And this works perfectly.
Any idea how I might be able to do this with just the standard net/http
signature and way of defining middleware handlers that look like this:
http.Handle("/", middlewareOne(middlewareTwo(finalHandler)))
Thank you
答案1
得分: 1
可以使用http.Handler
来完成翻译:
func Auth(n http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("开始")
n.ServeHTTP(w, r)
log.Printf("结束")
})
}
func processReq(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("成功"))
}
func main() {
handler := http.HandlerFunc(processReq)
http.Handle("/",Auth(handler))
http.ListenAndServe(":8000", nil)
}
希望这可以帮助到你!
英文:
func Auth(n http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Start")
n.ServeHTTP(w, r)
log.Printf("End")
})
}
func processReq(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Success"))
}
func main() {
handler := http.HandlerFunc(processReq)
http.Handle("/",Auth(handler))
http.ListenAndServe(":8000", nil)
}
can be done using http.handler
答案2
得分: 0
简单。你可以像这样定义每个处理程序:
// 为了不重复输入...
type HTTPHandler func(w http.ResponseWriter, r *http.Request)
func Handler1(next HTTPHandler) HTTPHandler {
return func(w http.ResponseWriter, r *http.Request){
// 做一些事情
if next != nil {
next(w, r)
}
}
}
// Handler2 ... HandlerN 以相同的基本方式定义。
// 链接:
http.Handle("/", Handler1(Handler2(nil)))
每个处理程序接受下一个处理程序,并返回一个闭包,该闭包执行你想要的操作,并调用下一个处理程序。如果你需要很多这样的处理程序,可能有必要编写一个类似于以下示例的辅助函数:
func MakeHandler(worker, next HTTPHandler) HTTPHandler {
return func(w http.ResponseWriter, r *http.Request){
// 可能需要让 worker 返回一个错误,并在这里进行标准错误处理?
// 根据你的具体情况,这可能会简化你的代码。
worker(w, r)
if next != nil {
next(w, r)
}
}
}
英文:
Simple. You define each handler like so:
// So I don't have to type it over and over...
type HTTPHandler func(w http.ResponseWriter, r *http.Request)
func Handler1(next HTTPHandler) HTTPHandler {
return func(w http.ResponseWriter, r *http.Request){
// Do stuff
if next != nil {
next(w, r)
}
}
}
// Handler2 ... HandlerN defined in the same basic way.
// Chaining:
http.Handle("/", Handler1(Handler2(nil)))
Each handler takes the next handler and returns a closure that does whatever you want plus calling the next handler. If you need lots of these it may make sense to write a helper similar to this one:
func MakeHandler(worker, next HTTPHandler) HTTPHandler {
return func(w http.ResponseWriter, r *http.Request){
// Maybe have to worker return an error and do standard error
// handling here? Could simplify your code some depending on
// what you are doing.
worker(w, r)
if next != nil {
next(w, r)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论