【问题标题】:How to Use Specific middleware for specific routes in a Get Subrouter in gorilla mux如何在 gorilla mux 的 Get Subrouter 中为特定路由使用特定中间件
【发布时间】:2021-02-22 09:27:33
【问题描述】:

我对 Gorilla mux 路由有一个特定要求,我想为一个子路由器下的不同路由添加不同的中间件(在我的例子中是 GET 子路由器)。下面是我的路由代码:

    // create a serve mux
    sm := mux.NewRouter()

    // register handlers
    postR := sm.Methods(http.MethodPost).Subrouter()
    postR.HandleFunc("/signup", uh.Signup)
    postR.HandleFunc("/login", uh.Login)
    postR.Use(uh.MiddlewareValidateUser)

    getR := sm.Methods(http.MethodGet).Subrouter()
    getR.HandleFunc("/refresh-token", uh.RefreshToken)
    getR.HandleFunc("/user-profile", uh.GetUserProfile)

在上述路由器逻辑中,我的 /refresh-token 和 /user-profile 令牌都属于 getR 路由器。我还有两个名为 ValidateAccessToken 和 ValidateRefreshToken 的中间件函数。我想将 ValidateRefreshToken 中间件函数用于“/refresh-token”路由,并将 ValidateAccessToken 用于 GET 子路由器下的所有其他路由。我想用 Gorilla mux 路由本身来做到这一点。请建议我完成上述场景的适当方法。感谢您的时间和精力。

【问题讨论】:

    标签: go routes gorilla


    【解决方案1】:

    还有一个

    使用示例

    mux := mux.NewRouter()
    healthRoute := mux.Path("/health").Handler(healthHandler)
    mux.PathPrefix("/").Handler(defaultHandler)
    
    // Run logging middleware except on the health route because health is spammy
    mux.Use(libHttp.MiddlewareExcept(libHttp.LoggingMiddlewareWith404(logger), healthRoute))
    

    然后实现

    // MiddlewareExcept returns a new middleware that calls the provided middleware except on the provided routes
    func MiddlewareExcept(middleware mux.MiddlewareFunc, routes ...*mux.Route) mux.MiddlewareFunc {
        routeMatch := mux.RouteMatch{}
        return func(next http.Handler) http.Handler {
            return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
                for _, route := range routes {
                    if route.Match(r, &routeMatch) {
                        if next != nil {
                            next.ServeHTTP(rw, r)
                        }
                    } else {
                        middleware(next).ServeHTTP(rw, r)
                    }
                }
            })
        }
    }
    

    【讨论】:

      【解决方案2】:

      notorious.no 提供的解决方案也可以完美地满足给定的要求。我还遇到了另一个使用 PathPrefix 并解决相同问题的解决方案,并希望获得相同的建议。

          // create a serve mux
          sm := mux.NewRouter()
      
          // register handlers
          postR := sm.Methods(http.MethodPost).Subrouter()
          postR.HandleFunc("/signup", uh.Signup)
          postR.HandleFunc("/login", uh.Login)
          postR.Use(uh.MiddlewareValidateUser)
      
          refToken := sm.PathPrefix("/refresh-token").Subrouter()
          refToken.HandleFunc("", uh.RefreshToken)
          refToken.Use(uh.MiddlewareValidateRefreshToken)
      
          getR := sm.Methods(http.MethodGet).Subrouter()
          getR.HandleFunc("/greet", uh.Greet)
          getR.Use(uh.MiddlewareValidateAccessToken)
      

      使用参考来到这个解决方案:https://github.com/gorilla/mux/issues/360

      【讨论】:

        【解决方案3】:

        我有一个类似的用例,这是我如何解决它的一个例子:

        package main
        
        import (
            "log"
            "net/http"
            "time"
        )
        
        import (
            "github.com/gorilla/mux"
        )
        
        // Adapter is an alias so I dont have to type so much.
        type Adapter func(http.Handler) http.Handler
        
        // Adapt takes Handler funcs and chains them to the main handler.
        func Adapt(handler http.Handler, adapters ...Adapter) http.Handler {
            // The loop is reversed so the adapters/middleware gets executed in the same
            // order as provided in the array.
            for i := len(adapters); i > 0; i-- {
                handler = adapters[i-1](handler)
            }
            return handler
        }
        
        // RefreshToken is the main handler.
        func RefreshToken(res http.ResponseWriter, req *http.Request) {
            res.Write([]byte("hello world"))
        }
        
        // ValidateRefreshToken is the middleware.
        func ValidateRefreshToken(hKey string) Adapter {
            return func(next http.Handler) http.Handler {
                return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
                    // Check if a header key exists and has a value
                    if value := req.Header.Get(hKey); value == "" {
                        res.WriteHeader(http.StatusForbidden)
                        res.Write([]byte("invalid request token"))
                        return
                    }
        
                    // Serve the next handler
                    next.ServeHTTP(res, req)
                })
            }
        }
        
        // MethodLogger logs the method of the request.
        func MethodLogger() Adapter {
            return func(next http.Handler) http.Handler {
                return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
                    log.Printf("method=%s uri=%s\n", req.Method, req.RequestURI)
                    next.ServeHTTP(res, req)
                })
            }
        }
        
        func main() {
            sm := mux.NewRouter()
            getR := sm.Methods(http.MethodGet).Subrouter()
            getR.HandleFunc("/refresh-token", Adapt(
                http.HandlerFunc(RefreshToken),
                MethodLogger(),
                ValidateRefreshToken("Vikee-Request-Token"),
            ).ServeHTTP)
        
            srv := &http.Server{
                Handler:      sm,
                Addr:         "localhost:8888",
                WriteTimeout: 30 * time.Second,
                ReadTimeout:  30 * time.Second,
            }
            log.Fatalln(srv.ListenAndServe())
        }
        

        Adapt 函数允许您将多个处理程序链接在一起。我已经演示了 2 个中间件函数(ValidateRefreshTokenMethodLogger)。中间件基本上是闭包。您可以将此方法用于任何接受http.Handler 的框架,例如muxchi

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-11-30
          • 1970-01-01
          • 2014-12-16
          • 1970-01-01
          • 2015-06-17
          • 1970-01-01
          • 2015-04-05
          • 1970-01-01
          相关资源
          最近更新 更多