Overriding HTTP Headers from External Go Middleware
Background
Middleware in Go is used to intercept and modify requests and responses before they reach the handler. However, when multiple middleware components modify the same header, it can result in multiple instances of that header being set in the response.
Consider the following example middleware:
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) }) }
When this middleware is used along with other middleware that sets the "Server" header, it results in multiple "Server" headers in the response.
Custom ResponseWriter
To resolve this issue, we can create a custom ResponseWriter that intercepts the WriteHeader() call and sets the appropriate header before passing the request further.
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() }
By using this custom ResponseWriter in our Server middleware, we can ensure that the "Server" header is set only once.
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) }) }
This solution allows us to control the HTTP headers from outer middleware without violating the semantics of ServeHTTP.
The above is the detailed content of How to Override HTTP Headers in Go Middleware Without Duplication?. For more information, please follow other related articles on the PHP Chinese website!