我正在构建一个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
签名以及定义如下所示的中间件处理程序的方式来做到这一点:
http.Handle("/", middlewareOne(middlewareTwo(finalHandler)))
谢谢:)
答案 0 :(得分:1)
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)
}
可以使用http.handler
完成答案 1 :(得分:0)
简单。您可以像这样定义每个处理程序:
// 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)))
每个处理程序获取下一个处理程序并返回一个闭包,它可以执行任何操作并调用下一个处理程序。如果你需要很多这样的东西,写一个类似于这个的帮手可能是有意义的:
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)
}
}
}