我希望从我的处理程序中提取一些重复的逻辑,并将其放入某些处理程序中间件中:特别是CSRF检查、检查现有会话值(即用于auth或预览页)等。
我读过关于这个的几篇文章,但是很多例子都集中在每台服务器的中间件(包装http.Handler)上:我有一组更小的处理程序,需要中间件。我的大多数其他页面没有,因此,如果我能够避免检查会话/等等,那么这些请求越好越好。
到目前为止,我的中间件通常如下所示:
func checkCSRF(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// get the session, check/validate/create the token based on HTTP method, etc.
// return HTTP 403 on a failed check
// else invoke the wrapped handler h(w, r)
}
}但是,在许多情况下,我希望将一个变量传递给包装处理程序:一个生成的CSRF令牌传递给模板,或者一个包含表单数据的结构--一个中间件在用户点击/preview/ URL之前检查会话中是否存在一些已保存的表单数据,否则它会将它们重定向出去(因为它们没有什么可预览的!)。
我希望将该结构传递给包装处理程序,以保存必须复制session.Get/type断言/错误检查逻辑(我刚刚在中间件中编写的逻辑)。
我可以写这样的东西:
type CSRFHandlerFunc func(w http.ResponseWriter, r *http.Request, t string)..。然后编写如下中间件:
func csrfCheck(h CSRFHandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// get the session, check/validate/create the/a token based on HTTP method, etc.
// return HTTP 403 on a failed check
// else invoke the wrapped handler and pass the token h(w, r, token)
}..。但这提出了几个问题:
r.HandleFunc("/path/preview/", checkCSRF(checkExisting(previewHandler)))吗?我在这里看到的问题是,中间件现在是紧密耦合的:包装的中间件现在需要接收并传递来自外部中间件的变量。这使得扩展http.HandlerFunc变得更棘手/更复杂。在可能的情况下,我试图避免落入“不要被捕捉到编写库”的陷阱中,但是中间件是我可能在项目后期添加/构建的东西,我希望第一次“正确”。
如能就此提供一些指导,将不胜感激。到目前为止,Go在编写web应用程序方面做得很好,但在这个阶段还没有太多的例子,因此,我还有点依赖于它。
发布于 2013-11-05 13:17:26
如果我正确理解了您的问题,您正在寻找一种向中间件传递附加参数的方便方法,对吗?
现在,定义这些参数是很重要的。它们可能是中间件的一些配置值--这些值可以在构建Handler类型时设置)。而不是NewMyMiddleware(MyHandler),而是NewMyMiddleware(MyHandler, "parameter"),这里没有问题。
但在您的情况下,您似乎希望传递每个请求参数,比如CSRF令牌。将这些信息传递到处理程序函数中将修改其签名,并且它将偏离标准的Handler[Func]接口。在这种情况下,中间件更紧密地耦合是正确的。
您自己也提到了解决方案--在我看来,上下文映射是,是一个可行的工具。这并不是说很难自己编写一个--您基本上需要一个map[*http.Request]interface{}和一个RWMutex来实现安全的并发访问。不过,简单地使用gorilla/context就足够了--它似乎是一个(相对)成熟的、编写良好的包,它有一个很好的API。
无耻的插头:如果你在处理CSRF支票,为什么不试试我的浪花包呢?
https://stackoverflow.com/questions/19784687
复制相似问题