An Interceptor wraps an http.ResponseWriter so middleware can observe or alter selected response-writing calls without changing handlers. It remains usable as a ResponseWriter, captures WriteHeader status codes, then forwards the call to the original writer so the response proceeds normally. section 9.3 section 9.3.1
Figure 9.4 Interceptor captures HTTP status codes by intercepting WriteHeader. Then Interceptor forwards the call to the underlying ResponseWriter.
The wrapper sits between a handler and its original response writer: it records the status code at WriteHeader, then delegates the write. section 9.3
Embed http.ResponseWriter anonymously and define only the method that needs interception. Promoted methods continue to reach the embedded writer, while Interceptor.WriteHeader takes precedence, calls an optional OnWriteHeader hook, and then invokes the embedded writer’s WriteHeader method. section 9.3.1
Listing 9.6 Intercepting method calls (link/kit/hlog/hlog.go)
// Interceptor provides hooks to intercept response writes.
type Interceptor struct {
http.ResponseWriter #1
OnWriteHeader func(code int) #2
}
// WriteHeader calls [Interceptor.OnWriteHeader] if provided and
// then calls the embedded [http.ResponseWriter.WriteHeader].
func (ic *Interceptor) WriteHeader(code int) {
if ic.OnWriteHeader != nil { #3
ic.OnWriteHeader(code) #3
} #3
ic.ResponseWriter.WriteHeader(code) #4
}
This implementation keeps the wrapper focused: a hook receives the code before delegation to the embedded ResponseWriter. section 9.3.1
StatusCode middleware creates an Interceptor for one request and supplies a hook that saves the observed code. Initialize the destination to http.StatusOK before calling the next handler, because the server uses OK when a handler never explicitly calls WriteHeader. The supplied integer is not safe for concurrent use. section 9.3.2
Preserving streaming behavior
Embedding the ResponseWriter interface does not expose optional methods implemented only by its runtime value, such as http.Flusher.Flush. Add Unwrap to return the original writer so ResponseController and wrapper-aware code can reach optional functionality; direct type assertions against the wrapper can still fail in older code. section 9.4.1 section 9.4.3
Listing 9.9 Unwrap (link/kit/hlog/hlog.go)
// Unwrap returns the embedded [http.ResponseWriter] to allow
// handlers to access the original when needed to preserve
// [http] optional interfaces like [http.Flusher], etc.
func (ic *Interceptor) Unwrap() http.ResponseWriter {
return ic.ResponseWriter #1
}
Unwrap exposes the embedded response writer, allowing wrapper-aware HTTP facilities to find optional behavior beneath the Interceptor. section 9.4.3

