为了账号安全,请及时绑定邮箱和手机立即绑定

编写每个处理程序中间件

编写每个处理程序中间件

Go
江户川乱折腾 2021-06-30 09:53:47
我希望从我的处理程序中提取一些重复的逻辑并将其放入一些每个处理程序的中间件中:特别是 CSRF 检查、检查现有会话值(即身份验证或预览页面)等。我已经阅读了一些关于此的文章,但许多示例都集中在每个服务器的中间件(包装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 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 更棘手/更复杂。将大猩猩/背景更适合这里,让我避免写2-3自定义的处理器类型(或通用处理器类型) -如果有的话,我会如何利用它?或者我可以实现我自己的“上下文”映射(并遇到并发访问问题?)。在可能的情况下,我试图避免陷入“不要陷入编写库”的陷阱,但是中间件是我可能会在项目生命后期添加/构建的东西,我想“第一次做对”。对此的一些指导将不胜感激。到目前为止,Go在编写 Web 应用程序方面非常出色,但在其生命周期的现阶段还没有大量示例,因此我有点依赖 SO。
查看完整描述

1 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

如果我正确理解了您的问题,那么您正在寻找一种方便的方法来将附加参数传递给您的中间件,对吗?

现在,定义这些参数是什么很重要。它们可能是您的中间件的一些配置值——可以在构造 Handler 类型时设置这些值)。而不是NewMyMiddleware(MyHandler),你做NewMyMiddleware(MyHandler, "parameter"),这里没问题。

但是在您的情况下,您似乎想传递每个请求的参数,例如 CSRF 令牌。将这些传递给处理函数会修改其签名,并且会偏离标准Handler[Func]接口。在这种情况下,您对中间件的耦合更加紧密是正确的。

你自己提到了解决方案——在我看来,上下文地图一个可行的工具。这不是很难一个写自己-你基本上需要map[*http.Request]interface{}RWMutex安全的并发访问。尽管如此,简单地使用gorilla/context应该就足够了——它似乎是一个(相对)成熟的、编写良好的包,带有一个很好的 API。

无耻的插件:如果你正在处理 CSRF 检查,为什么不试试我的nosurf包?


查看完整回答
反对 回复 2021-07-05
  • 1 回答
  • 0 关注
  • 199 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信