Panic no more, Mux
In last article Collect Mux metrics. I wrote about how to collect metrics data in a middleware. This article I’ll write about how to recover from panic in a middleware using Mux.
In the web framework, like Gin, Rails, Tornado, whenever there’s an internal
server error, the framework will catch the error and render the internal server
error from top level. But if you’re using Mux, it’s not built-in natively, so if
the app crashes internally, it’ll not raise a 500 error and sometimes return
error 405 Method Not Allowed
. Hoever Mux does come with this feature, it’s in
https://github.com/gorilla/handlers.
We’ll need to enable this before using it.
The package has this function called RecoveryHandler
, let’s utilize this
function to recover from panic. First, we need to create the middleware
// RecoveryMiddleware is the rescue to panic
type RecoveryMiddleware struct {
}
// Middleware recovers from panic
func (middleware *RecoveryMiddleware) Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next = handlers.RecoveryHandler()(next)
next.ServeHTTP(w, r)
})
}
Then we can apply this middleware
router := mux.NewRouter().
recoveryMiddleware := RecoveryMiddleware{}
router.Use(recoveryMiddleware.Middleware)
How do we test this middleware? The fisrt question is how to test panic? Here’s
what recover
come to play. Recover is a built-in function that regains control
of a panicking goroutine, and it is only useful inside deferred functions. So
the test would be like
It("Panics without the middleware", func() {
req := httptest.NewRequest("GET", "/test", nil)
w := httptest.NewRecorder()
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic", r)
}
}()
http.HandlerFunc(handler).ServeHTTP(w, req)
log.Fatal("No panic")
})