go 23 lines · 1 tab

Capture status code and bytes written via ResponseWriter wrapper

Leah Thompson Jan 2026
1 tab
package middleware

import "net/http"

type StatusRecorder struct {
  http.ResponseWriter
  Status int
  Bytes  int64
}

func (sr *StatusRecorder) WriteHeader(code int) {
  sr.Status = code
  sr.ResponseWriter.WriteHeader(code)
}

func (sr *StatusRecorder) Write(p []byte) (int, error) {
  if sr.Status == 0 {
    sr.Status = http.StatusOK
  }
  n, err := sr.ResponseWriter.Write(p)
  sr.Bytes += int64(n)
  return n, err
}
1 file · go Explain with highlit

When you need accurate request logs or metrics, you can’t rely on “what you intended to write” — you need what actually got written. Wrapping http.ResponseWriter to capture WriteHeader and count bytes is a simple way to record status codes and response sizes without changing every handler. This is also the foundation for middleware that emits access logs or Prometheus metrics. The key is correctness: default status should be 200 if WriteHeader is never called, and Write should ensure status is set before counting bytes. In production, I also capture duration, route name, and request ID. This keeps logging out of business logic and gives you consistent telemetry for debugging. It’s an old pattern, but it remains one of the most useful pieces of plumbing in Go HTTP servers.


Related snips

Share this code

Here's the card — post it anywhere.

Capture status code and bytes written via ResponseWriter wrapper — share card
Link copied