Golang Web--中间件的学习总结
关于在golang中的中间件,可以翻阅笔者之前的博客,在这里不予详细说明。这里简单介绍下中间件的高级用法:
1.如果每个路由分别要配置多个中间价,该如何处理
2.如果有多个路由分别要配置多个中间件,该如何处理
3.尝试不定义结构体开发中间件
package main import ( "context" "fmt" "log" "net/http" "time" ) type Middleware func(http.HandlerFunc) http.HandlerFunc func GetAuthCode() Middleware { return func(f http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { code := 0 if r.URL.Path != "/" { code = -1 } ctxWithUser := context.WithValue(r.Context(), code, "User") rWithUser := r.WithContext(ctxWithUser) f(w, rWithUser) } } } func EnsureAuth() Middleware { return func(hf http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { user := r.Context().Value(0) if user != nil { log.Println("auth available") } else { http.Error(w, "please sign in", http.StatusUnauthorized) return } hf(w, r) } } } func Logging() Middleware { return func(hf http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { start := time.Now() defer func() { log.Println(r.URL.Path, time.Since(start)) }() hf(w, r) } } } func Mehtod(m string) Middleware { return func(hf http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != m { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } else { log.Println("request:", m) } hf(w, r) } } } func Chain(f http.HandlerFunc, midddlewares ...Middleware) http.HandlerFunc { for _, m := range midddlewares { f = m(f) } return f } func Hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello word") } func Auth(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "you have get auth") } func main() { http.HandleFunc("/", Chain(Hello, Mehtod("GET"), GetAuthCode(), Logging())) http.HandleFunc("/auth", Chain(Auth, Mehtod("GET"), GetAuthCode(), EnsureAuth(), Logging())) http.ListenAndServe(":7788", nil) }
Hello,Auth是对两个路由的注册函数,其中Chain的参数包括handlefunc类型的函数,middleware类型的不定长参数,这里可以为每个路由指定多个路由中间件。