大猩猩mux中间件:包装一个处理程序



我需要将GetAssetsCompute函数封装在中间件中

r.Handle("/api/v1/assets/ComputeBlade", GetAssetsCompute(assetService)).Methods("GET")
func GetAssetsCompute(assetService ServiceType) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//  stuff here
})
}

但是因为中间件将HTTP处理程序作为一个参数,而我的函数不是处理程序,所以我不能。

我想做这样的事。

func GetAssetsCompute(assetService ServiceType) http.Handler {
return MyMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//  stuff here
}))
}

func MyMiddleware(next http.Handler) http.Handler {
}

这是正确的吗?或者有更好的方法可以做到这一点。同样在中间件内部,我需要访问URL端点,进行一些处理并存储处理后的值,然后再次访问主处理程序中的值。我该怎么做?

编辑:我只想将这个中间件应用于我拥有的端点的子集(>1(。并非所有

我还需要处理程序中GetAssetsCompute(assetService ServiceType)函数中使用的assetService变量。所以,我也需要这个结束。

您似乎在尝试做两件事。1-只将中间件应用于某些请求处理程序。2-将数据从中间件传递到请求处理程序。

对于第一种,我可以想到三种选择。第一个是您现在正在做的事情,有一个中间件函数,当您将处理程序函数传递给r.Handle时,您可以在其中封装处理程序函数。伪码:

r.Handle("/path1", Mware(Handler1())).Methods("GET")
r.Handle("/path2", Mware(Handler2())).Methods("GET")
r.Handle("/path3-nomiddleware", Handler3()).Methods("GET")

您可以做的第二件事是向中间件添加代码,以便根据URI路径进行筛选,然后使用r.Use注册中间件。伪码:

const mwarePaths []string = ...
func Mware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.RequestURI is in mwarePaths {
// do the middleware
}
}
}
r.Use(Mware)

第三,您可以将代码放在一个函数中,直接在处理程序中调用该函数,而不是像中间件一样注册它。伪码:

func myUtil(w http.ResponseWriter, r *http.Request){ ... }
func GetAssetsCompute(assetService ServiceType) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
myUtil(w, r)
//  stuff here
})
}

第二件事——将数据从中间件传递到请求处理程序——这里有一些想法。

首先,如果使用常规函数,而没有上面的中间件设置,那么这个问题就会消失,因为处理程序中需要的任何东西都可以是函数的返回值。

如果您确实使用了中间件,那么可以使用context库(同样来自gorilla(将变量绑定到http。请求传递给处理程序的实例:http://www.gorillatoolkit.org/pkg/context。使用看起来像这样:

import "github.com/gorilla/context"
func middleware(...) {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
context.Set(r, "myKey", "bar")
}
}
func handler(w http.ResponseWriter, r *http.Request) {
val, ok := context.GetOk(r, "myKey") // returns "bar", true
}

你选择使用这些选项中的哪一个取决于你(你知道自己的需求(。但是,正如评论中提到的,一个很好的经验法则是,处理与请求处理程序无关的问题的代码可以是中间件。处理与请求处理程序正在做的事情直接相关的关注点的代码可以直接进入处理程序。

最新更新