首页 > 解决方案 > 从 router.HandleFunc 调用返回多个中间件函数

问题描述

我正在使用 gorilla/mux 我有这个:

router.HandleFunc("/api/v1/register",h.makeRegisterNewUser(v)).Methods("POST")

看起来h.makeRegisterNewUser像:

func (h Handler) makeRegisterNewUser(v interface{}) http.HandlerFunc {

    type RespBody = ...;
    type ReqBody = ...


    return func(w http.ResponseWriter, r *http.Request) {

        decoder := json.NewDecoder(r.Body)
        err := decoder.Decode(&ReqBody)

        // ...

        json.NewEncoder(w).Encode(RespBody{});
    }
}

我的问题是 - 有没有办法从 makeRegisterNewUser 返回多个 http.HandlerFuncs?像这样的东西:

router.HandleFunc("/api/v1/register",h.makeRegisterNewUser(v)).Methods("POST")

func (h Handler) makeRegisterNewUser(v interface{}) (http.HandlerFunc...) {

    type RespBody = ...;
    type ReqBody = ...


    return func(w http.ResponseWriter, r *http.Request) {
       // 1

    }, func(w http.ResponseWriter, r *http.Request) {
       // 2

    }, func(w http.ResponseWriter, r *http.Request) {
        // 3
    }
}

我不确定中间件是否可以像在 Node.js Express 中那样在 Go 中链接。

标签: gogorilla

解决方案


You can chain multiple http.Handler using wrapper:

type Middleware struct {
    next          http.Handler
}

func (m Middleware) Wrap(handler http.Handler) http.Handler {
    m.next = handler
    return m
}

func (m Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // run your handler code here
    // write error into w and return if you need to interrupt request execution

    // call next handler 
    m.next.ServeHTTP(w, r)
}

Register chained wrappers and main handler:

h1 := Middleware{}
h2 := OtherMiddleware{}
router.Handle("/some_route", h1.Wrap(h2.Wrap(mainHandler))).Methods(http.MethodPost)

Request will execute h1, h2 and finally mainHandler.

For example, you can log request in h1, authorize in h2 and keep business logic in mainHandler.


推荐阅读