package middleware import ( "net/http" ) // responseRecorder remembers the status code and byte count for the // logger and the metrics middleware. net/http gives no way to read // them back off an http.ResponseWriter, so the only way to know what // was answered is to be the thing that answered it. type responseRecorder struct { http.ResponseWriter status int written int64 wrote bool } func newResponseRecorder(w http.ResponseWriter) *responseRecorder { // A handler that writes a body without calling WriteHeader has // sent 200; recording that up front means Status() is right for // the common case without waiting for a call that never comes. return &responseRecorder{ResponseWriter: w, status: http.StatusOK} } func (r *responseRecorder) WriteHeader(status int) { if r.wrote { return } r.status = status r.wrote = true r.ResponseWriter.WriteHeader(status) } func (r *responseRecorder) Write(b []byte) (int, error) { r.wrote = true n, err := r.ResponseWriter.Write(b) r.written += int64(n) //nolint:wrapcheck // pass-through writer: wrapping would obscure the underlying error. return n, err } // Status returns the status code that was sent. func (r *responseRecorder) Status() int { return r.status } // Written reports whether anything has been sent yet. The panic // recoverer needs this: it can only substitute a 500 for a response // that has not started. func (r *responseRecorder) Written() bool { return r.wrote } // Unwrap lets http.ResponseController reach the underlying writer, so // wrapping does not cost the handler flushing or deadline control. func (r *responseRecorder) Unwrap() http.ResponseWriter { return r.ResponseWriter }