Go HTTP 中间件详解
别再把同样的代码复制粘贴到每一个 handler 中了。
如果你需要检查身份验证、记录请求耗时或为每个请求添加唯一 ID,请不要将这些逻辑写在你的业务 handler 中。如果你有 20 个 handler,那么当身份验证逻辑发生变化时,你就需要修改 20 个地方。这简直是维护噩梦。
中间件解决了这个问题。你只需编写一次逻辑,将其包装在你的 handler 之外,之后就再也不用动它了。
什么是中间件?
在 Go 中,中间件是一个满足以下条件的函数: • 接收一个 http.Handler。 • 返回一个新的 http.Handler。 • 在原始 handler 运行之前或之后执行操作。
把它想象成一个洋葱。每一层都包裹着下一层。请求在进入时会经过每一层,响应在返回时也会经过每一层。
你将学到:
• http.Handler 接口的基础知识。 • 如何从零开始构建自定义中间件。 • 如何将多个层级串联在一起。 • 如何使用 context 在链条中传递数据。 • 高级技巧,如执行顺序和 panic 恢复。
核心要点:
• 顺序至关重要。如果一个中间件在 context 中设置了一个值,那么链条中的下一个中间件必须是读取该值的那个。如果你交换了它们的顺序,数据将会为空。
• 提前退出后务必 return。如果你发现错误并发送了 http.Error,请立即调用 return。如果你在发送错误后又调用了 next.ServeHTTP,你的服务器将会发生 panic。
• 为 context 键使用自定义类型。不要使用普通的字符串作为键。这可以防止不同的包互相覆盖数据。
• 使用包装器(wrapper)来捕获数据。由于标准的 http.ResponseWriter 在写入状态码后不允许你再次读取,因此你必须创建一个自定义结构体来拦截并保存它,以便进行日志记录。
通过掌握这些模式,为你的 Go HTTP 服务器打下坚实的基础。
