diff --git a/middlewares/recover.go b/middlewares/recover.go new file mode 100644 index 000000000..3b8475d2a --- /dev/null +++ b/middlewares/recover.go @@ -0,0 +1,32 @@ +package middlewares + +import ( + "github.com/codegangsta/negroni" + "github.com/containous/traefik/log" + "net/http" +) + +// RecoverHandler recovers from a panic in http handlers +func RecoverHandler(next http.Handler) http.Handler { + fn := func(w http.ResponseWriter, r *http.Request) { + defer recoverFunc(w) + next.ServeHTTP(w, r) + } + return http.HandlerFunc(fn) +} + +// NegroniRecoverHandler recovers from a panic in negroni handlers +func NegroniRecoverHandler() negroni.Handler { + fn := func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + defer recoverFunc(w) + next.ServeHTTP(w, r) + } + return negroni.HandlerFunc(fn) +} + +func recoverFunc(w http.ResponseWriter) { + if err := recover(); err != nil { + log.Errorf("Recovered from panic in http handler: %+v", err) + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + } +} diff --git a/server/server.go b/server/server.go index da99e366d..008699651 100644 --- a/server/server.go +++ b/server/server.go @@ -173,7 +173,7 @@ func (server *Server) startHTTPServers() { server.serverEntryPoints = server.buildEntryPoints(server.globalConfiguration) for newServerEntryPointName, newServerEntryPoint := range server.serverEntryPoints { - serverMiddlewares := []negroni.Handler{server.loggerMiddleware, metrics} + serverMiddlewares := []negroni.Handler{middlewares.NegroniRecoverHandler(), server.loggerMiddleware, metrics} if server.globalConfiguration.Web != nil && server.globalConfiguration.Web.Metrics != nil { if server.globalConfiguration.Web.Metrics.Prometheus != nil { metricsMiddleware := middlewares.NewMetricsWrapper(middlewares.NewPrometheus(newServerEntryPointName, server.globalConfiguration.Web.Metrics.Prometheus))