Skip to content

Instantly share code, notes, and snippets.

@Boerworz
Last active August 14, 2024 06:41
Show Gist options
  • Save Boerworz/b683e46ae0761056a636 to your computer and use it in GitHub Desktop.
Save Boerworz/b683e46ae0761056a636 to your computer and use it in GitHub Desktop.
Capturing the HTTP status code from http.ResponseWriter
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
// We need to cast handleRoot to a http.HandlerFunc since wrapHandlerWithLogging
// takes a http.Handler, not an arbitrary function.
handler := wrapHandlerWithLogging(http.HandlerFunc(handleRoot))
http.Handle("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
// ---- Handlers
func handleRoot(w http.ResponseWriter, req *http.Request) {
if req.URL.Path != "/" {
http.NotFound(w, req)
return
}
fmt.Fprintf(w, "Hello, World!")
}
// ---- Logging
func wrapHandlerWithLogging(wrappedHandler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
log.Printf("--> %s %s", req.Method, req.URL.Path)
lrw := NewLoggingResponseWriter(w)
wrappedHandler.ServeHTTP(lrw, req)
statusCode := lrw.statusCode
log.Printf("<-- %d %s", statusCode, http.StatusText(statusCode))
})
}
type loggingResponseWriter struct {
http.ResponseWriter
statusCode int
}
func NewLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWriter {
// WriteHeader(int) is not called if our response implicitly returns 200 OK, so
// we default to that status code.
return &loggingResponseWriter{w, http.StatusOK}
}
func (lrw *loggingResponseWriter) WriteHeader(code int) {
lrw.statusCode = code
lrw.ResponseWriter.WriteHeader(code)
}
@xen-HendryZheng
Copy link

the solution works ! But can you explain when and where did WriteHeader is being called / invoke?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment