package middleware
import (
"log"
"net/http"
"runtime/debug"
)
func Recover(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if p := recover(); p != nil {
log.Printf("panic: %v
%s", p, debug.Stack())
http.Error(w, "internal server error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}
Even well-tested services panic occasionally: a nil pointer from an unexpected edge case, a slice bounds bug, or a library doing something surprising. If you don’t recover, one request can crash the entire process and turn a small bug into an outage. I wrap my HTTP stack with a recovery middleware that catches panics, logs the panic value and stack trace, and returns a generic 500 to the client. The key is to avoid leaking internals: clients should see “internal server error” while logs contain the details. In production, I also include request identifiers (like X-Request-Id) and route labels so incidents are debuggable. This middleware doesn’t replace tests, but it’s a practical guardrail. When combined with alerting on panic count, it gives you early warning before a rare crash becomes a repeating failure pattern.
Related snips
package api
import (
"net/http"
"runtime/debug"
)
Expose build metadata for debugging deploys
export interface RetryOptions {
retries: number;
baseMs: number;
maxMs: number;
signal?: AbortSignal;
onRetry?: (attempt: number, delay: number, err: unknown) => void;
Exponential backoff with jitter for retries
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
package files
import (
"context"
"time"
Presigned S3 upload URLs (AWS SDK v2)
package deps
import (
"net"
"net/http"
"time"
HTTP client tuned for production: timeouts, transport, and connection reuse
package api
import (
"io"
"net/http"
"os"
Safe multipart uploads using temp files (bounded memory)
Share this code
Here's the card — post it anywhere.