Golang中间键

该文章节选自Mat Ryer-Medium

func log(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Before")
        h.ServeHTTP(w, r)
        fmt.Println("After")
    })
}

以上函数接受一个http.Handler参数,并在返回一个新的http.Handler之前或者之后进行一些操作

一个中间键类似包含如下的签名

func(http.Handler)http.Handler

在什么情况下使用中间件

  • 日志以及追踪
  • 请求验证
  • 编写通用的响应头部

访问控制

func checkAPIKey(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if len(r.URL.Query().Get("key")) == 0 {
            http.Error(w, "missing key", http.StatusUnauthorized)
            return
        }
        h.ServeHTTP(w, r)
    })
}

Deferring

func log(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Before")
        h.ServeHTTP(w, r)
        fmt.Println("After")
    })
}

利用Defer声明在goroutine发生panic后仍然可运行的特性,来捕获程序发生的异常

在中间件中添加自定义参数

func MustParams(h http.Handler, params ...string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        q := r.URL.Query()
        for _, param := range params {
            if len(q.Get(param)) == 0 {
                http.Error(w, "missing"+param, http.StatusBadRequest)
                return
            }
        }
        h.ServeHTTP(w, r)
    })
}

通过预先设置的参数列表,来限制请求,然后我们就可以如下进行调用

http.Handler("/user", MustParams(handleUser, "key", "auth"))

在中间件中使用中间件

func MustAuth(h http.Handler) http.Handler {
    checkauth := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        err := validateAuth(r.URL.Query().Get("auth"))
        if err != nil {
            http.Error(w, "bad auth param", http.StatusUnauthorized)
        }
        h.ServeHTTP(w, r)
    })
    return MustParams(checkauth, "auth")
}

在全局范围之内使用

routes := mux.NewRouter()
http.ListenAndServe(addr, log(serve))

results matching ""

    No results matching ""