HTTP error handling
With BunRouter, you can and should use middlewares to handle all errors from a single place. BunRouter does not provide a built-in error handler, but you can easily create your own.
For example, let's create an error handler for a JSON API that generates responses like this whenever there is an error:
{ "code": "login_required", "message": "You must log in before continuing" }
Let's start by defining a struct that will carry some information about an error:
type HTTPError struct { statusCode int Code string `json:"code"` Message string `json:"message"` } func (e HTTPError) Error() string { return e.Message }
Next, we need some logic to convert an error
into a HTTPError
:
func NewHTTPError(err error) HTTPError { switch err { case io.EOF: return HTTPError{ statusCode: http.StatusBadRequest, Code: "eof", Message: "EOF reading HTTP request body", } case sql.ErrNoRows: return HTTPError{ statusCode: http.StatusNotFound, Code: "not_found", Message: "Page Not Found", } } return HTTPError{ statusCode: http.StatusInternalServerError, Code: "internal", Message: "Internal server error", } }
Lastly, we need a middleware that pulls everything together:
func errorHandler(next bunrouter.HandlerFunc) bunrouter.HandlerFunc { return func(w http.ResponseWriter, req bunrouter.Request) error { // Call the next handler on the chain to get the error. err := next(w, req) switch err := err.(type) { case nil: // no error case HTTPError: // already a HTTPError w.WriteHeader(err.statusCode) _ = bunrouter.JSON(w, err) default: httpErr := NewHTTPError(err) w.WriteHeader(httpErr.statusCode) _ = bunrouter.JSON(w, httpErr) } return err // return the err in case there other middlewares } }
It is a good idea to isolate the API by creating a separate routing group and installing error handler only for that group:
api := router.NewGroup("/api", bunrouter.Use(errorHandler)) api.GET("/", indexHandler)
You can find the source code on GitHub.