从外部 Go 中间件控制 HTTP 标头
Go 中的 HTTP 中间件提供了一种便捷的方法来拦截和修改 HTTP 请求和响应。但是,从外部中间件控制标头可能具有挑战性,因为它需要覆盖现有标头而不引入重复项。
考虑以下设置“服务器”标头的服务器中间件:
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) }) }
当添加到响应链时,该中间件成功设置“Server”标头。但是,如果链中的任何其他处理程序也设置了“Server”标头,则重复的标头将导致响应。
出现挑战是因为 ServeHTTP 明确禁止在请求完成后写入 ResponseWriter。一种方法是创建一个自定义 ResponseWriter,拦截标头写入并在第一次写入之前插入“Server”标头。
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() } // Server attaches a Server header to the response. 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) }) }
通过使用自定义 ResponseWriter,我们可以确保添加“Server”标头仅一次,无论其他处理程序的行为如何。这种方法引入了额外的间接层,但它保留了所需的功能。
以上是Go中间件如何可靠地控制HTTP头而不重复?的详细内容。更多信息请关注PHP中文网其他相关文章!