从外部 Go 中间件覆盖 HTTP 标头
后台
Go 中的中间件用于在请求和响应到达处理程序之前拦截并修改它们。但是,当多个中间件组件修改同一标头时,可能会导致在响应中设置该标头的多个实例。
考虑以下示例中间件:
func Server(h http.Handler, serverName string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Server", serverName) h.ServeHTTP(w, r) }) }
当此中间件与设置“服务器”标头的其他中间件一起使用,它会在响应中产生多个“服务器”标头。
自定义ResponseWriter
要解决此问题,我们可以创建一个自定义 ResponseWriter,它会拦截 WriteHeader() 调用并在进一步传递请求之前设置适当的标头。
type serverWriter struct { w http.ResponseWriter name string wroteHeader bool } func (s serverWriter) WriteHeader(code int) { if s.wroteHeader == false { s.w.Header().Set("Server", s.name) s.wroteHeader = true } s.w.WriteHeader(code) } func (s serverWriter) Write(b []byte) (int, error) { return s.w.Write(b) } func (s serverWriter) Header() http.Header { return s.w.Header() }
通过使用在我们的服务器中间件中使用这个自定义的 ResponseWriter,我们可以确保“Server”标头仅设置一次。
func Server(h http.Handler, serverName string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { sw := serverWriter{ w: w, name: serverName, wroteHeader: false, } h.ServeHTTP(sw, r) }) }
这个该解决方案允许我们从外部中间件控制 HTTP 标头,而不违反 ServeHTTP 的语义。
以上是如何在 Go 中间件中重写 HTTP 标头而不重复?的详细内容。更多信息请关注PHP中文网其他相关文章!