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类型的不定长参数,这里可以为每个路由指定多个路由中间件。

posted @ 2023-06-04 18:26  99号的格调  阅读(47)  评论(0编辑  收藏  举报