Golang / GoLang Production Patterns and Web Standards Interview Questions
What is the standard Go HTTP middleware signature and how do you chain multiple middleware?
Go middleware follows a consistent adapter pattern: a function that accepts an http.Handler and returns a new http.Handler that wraps it. The signature func(http.Handler) http.Handler is the community standard — used by virtually every Go HTTP library.
// The standard middleware type type Middleware func(http.Handler) http.Handler // Logging middleware func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() // Wrap ResponseWriter to capture status code lrw := &loggingResponseWriter{ResponseWriter: w, statusCode: http.StatusOK} next.ServeHTTP(lrw, r) // call the next handler in the chain log.Printf("%s %s %d %v", r.Method, r.URL.Path, lrw.statusCode, time.Since(start)) }) } type loggingResponseWriter struct { http.ResponseWriter statusCode int } func (lrw *loggingResponseWriter) WriteHeader(code int) { lrw.statusCode = code lrw.ResponseWriter.WriteHeader(code) } // Auth middleware func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") if token == "" { http.Error(w, "unauthorized", http.StatusUnauthorized) return // short-circuit â next.ServeHTTP never called } next.ServeHTTP(w, r) }) } // Recovery middleware â catch panics in handlers func recoveryMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if rec := recover(); rec != nil { log.Printf("panic recovered: %v\n%s", rec, debug.Stack()) http.Error(w, "internal server error", http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } // Chaining middleware â applied right-to-left (outermost runs first) handler := recoveryMiddleware(loggingMiddleware(authMiddleware(mux))) // Request order: recovery â logging â auth â mux â handler // Cleaner chain helper func Chain(h http.Handler, middlewares ...Middleware) http.Handler { for i := len(middlewares) - 1; i >= 0; i-- { h = middlewares[i](h) } return h } handler = Chain(mux, recoveryMiddleware, loggingMiddleware, authMiddleware)
More Related questions...