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
			_ = bunrouter.JSON(w, err)
			httpErr := NewHTTPError(err)
			_ = 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 GitHubopen in new window.