Julien Sellier

Last update: 2024-12-29

Go Panic Recovery HTTP Middleware

package httpmux

import "net/http"

type PanicRecoveryHandler func(w http.ResponseWriter, r *http.Request, err any)

func NewPanicRecoveryMiddleware(onPanic PanicRecoveryHandler) func(http.Handler) http.Handler {
	if onPanic == nil {
		panic("missing panic handler")
	}

	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			defer func() {
				if err := recover(); err != nil {
					onPanic(w, r, err)
				}
			}()
			h.ServeHTTP(w, r)
		})
	}
}

Then wrap your main http.Handler:

package main

func panicRecoveryHandler(w http.ResponseWriter, r *http.Request, err any) {
	log.Println("panic recovered", err)
	http.Error(w, "Internal server error", http.StatusInternalServerError)
}

func main() {
	...
	httpHandler = NewPanicRecoveryMiddleware(panicRecoveryHandler)(httpHandler)
	...
}