go - 如何使用 gorilla mux 对所有路由应用相同的处理程序

标签 go handler gorilla mux

我正在使用有值(value)的 rootHandler处理产生的错误。我想知道如何将这个处理程序用于我的 api 可能服务的每个端点。

r := mux.NewRouter()

r.Handle("/api/endpoint0", rootHandler(function0)).Methods("POST")
r.HandleFunc("/api/endpoint1", function1).Methods("POST")
r.HandleFunc("/api/endpoint2", function2).Methods("POST")

    s := &http.Server{
        Handler:      r,
        Addr:         "127.0.0.1:8080",
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }

我的错误处理程序的工作方式如下:
type rootHandler func(http.ResponseWriter, *http.Request) error

func (fn rootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    err := fn(w, r) // Call handler function
    if err == nil {
        return
    }
    //log error or w/e
}

func NewHTTPError(err error, status int, detail string) error {
    return &HTTPError{
        Cause:  err,
        Detail: detail,
        Status: status,
    }
}

我正在使用的示例函数之一:
func function0(w http.ResponseWriter, r *http.Request) (err error) {
    if err = notLogged(); err != nil {
        return NewHTTPError(err, 400, "not authorized")
    }

}

我是否必须用 rootHanlder(functionName) 包装每个路由函数,还是有办法将它应用于每个路由?

最佳答案

取决于您的 rootHandler 的确切结构,您也许可以将其设置为中间件:

func GetRootHandlerMW(authUser SomeType) func(http.Handler) http.Handler {
  return func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Do what needs to be done?
        next.ServeHTTP(w, r)
    })
  }
}

...
r.Use(GetRootHandlerMW(authUser))

一个简单的日志中间件如下所示:
func LogMW(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        logRequest(...)
        next.ServeHTTP(w, r)
    })
}

...
r.Use(LogMW)

从您添加的代码中,您似乎想要更改 HTTP 处理程序函数以返回错误。这会更改函数的签名,您不能将其用作处理程序。您可以:
  • 使用上下文将错误传递回中间件。也就是说,在处理程序的请求上下文中设置一些错误值,以便记录器中间件可以在处理程序返回后记录它,或者
  • 就像你现在显然正在做的那样,用错误记录器包装每个处理程序。

  • 将值添加到上下文将创建一个新上下文,因此如果您使用上下文从处理程序传回值,则必须先设置一个占位符。像这样的东西:
    type RequestError struct {
       Err error
    }
    
    type requestErrorKeyType int
    const requestErrorKey requestErrorKeyType=iota
    
    func SetRequestError(req *http.Request, err error) {
       if r:=req.Context().Value(requestErrorKey); r!=nil {
           r.(*RequestError).Err=err
       }
    }
    
    // In the handler...
    requestError:=RequestError{}
    newReq:=request.WithContext(request.Context().WithValue(requestErrorKey,&requestError))
    next.ServeHTTP(w,newReq)
    if requestError.Err!=nil {
      ...
    }
    

    关于go - 如何使用 gorilla mux 对所有路由应用相同的处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61808751/

    相关文章:

    Go:使用 gorilla mux 提供 CSS 文件

    html - 使用 Go 提供 HTML 页面

    go - Kubernetes 自定义 CRD : "Failed to list ...: the server could not find the requested resource"

    android - 如何在 postDelayed 模式下停止 Handler?

    Go Gorilla RecoveryHandler 编译报错

    angularjs - FileServe和Routing的配合更流畅

    docker - "exec:\"scripts/script.sh\": stat scripts/script. sh: 没有那个文件或目录

    go - 具有结构体的结构体指针的接口(interface)的函数赋值显示不同的值

    android - 从服务到 Activity 的消息永远不会到达处理程序

    Android:从线程访问ui元素