你可以使用下面的例子,在Go应用程序中连锁HTTP服务器和路由器级别的中间件。一个中间件在每个请求中运行一次。服务器级别的中间件在每次请求到达时都会运行,无论调用的是哪个端点。然而,路由器级别的中间件是针对它所链接的端点运行的。
中间件
链中第一个添加的中间件最后运行。同时,服务器级别的中间件总是优先于路由器级别的中间件:
package middleware
import (
"net/http"
)
type (
// srv represents multi layer server level middleware list and is dedicated
// Server function.
srv func(http.Handler) http.Handler
// rtr represents multi layer router level middleware list and is dedicated
// to Router function.
rtr func(http.HandlerFunc) http.HandlerFunc
)
func Server(h http.Handler, mid ...srv) http.Handler {
for _, m := range mid {
h = m(h)
}
return h
}
func Router(h http.HandlerFunc, mid ...rtr) http.HandlerFunc {
for _, m := range mid {
h = m(h)
}
return h
}
使用实例
func Mid1(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, rq *http.Request) {
// Do something
h.ServeHTTP(rw, rq)
})
}
func Mid2(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, rq *http.Request) {
// Do something
h.ServeHTTP(rw, rq)
})
}
// This is how you wire them up.
s:= &http.Server{
Addr: ":8080",
Handler: middleware.Server(
someRouter,
Mid1,
Mid2,
),
}
路由器
func Mid1(handler http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, rq *http.Request) {
// Do something
handler(rw, rq)
}
}
func Mid2(handler http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, rq *http.Request) {
// Do something
handler(rw, rq)
}
}
// github.com/julienschmidt/httprouter
r := httprouter.New()
// This is how you wire them up.
r.HandlerFunc(
http.MethodGet,
"/leagues/:id",
middleware.Router(
league.Get,
Mid1,
Mid2,
))
// This does not use any middleware.
r.HandlerFunc(
http.MethodPost,
"/leagues",
league.Post,
))
// league.Post
func Get(rw http.ResponseWriter, rq *http.Request) {
// ...
}
// league.Post
func Post(rw http.ResponseWriter, rq *http.Request) {
// ...
}