Unified Error Handling Middleware for Golang HTTP

Unified error handling is implemented through middleware and the ErrorResponse structure, capturing panics and standardizing responses. The middleware uses defer and recover to prevent crashes, and the writeError function simplifies error returns, ensuring consistent and maintainable API error responses when integrated with routing.

Unified Error Handling Middleware for Golang HTTP

In Go language development for web services, unified error handling is key to ensuring consistency and maintainability of API responses. Through middleware mechanisms, we can centrally handle errors in HTTP requests and return a standardized error response format, avoiding scattered error handling code.

Please open in WeChat client

Unified Error Response Structure

Define a common error response format for easy parsing by the frontend and logging.

type ErrorResponse struct {    Code    int    `json:"code"`    Message string `json:"message"`    Data    any    `json:"data,omitempty"`}

This structure includes a status code, description, and an optional data field. Fields can be extended based on business needs, such as adding a request ID or timestamp.

Error Handling Middleware Implementation

The middleware captures panics and explicit errors during processing and converts them to a unified format for return.

func ErrorHandlingMiddleware(next http.Handler) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        // Capture panic        defer func() {            if err := recover(); err != nil {                w.Header().Set("Content-Type", "application/json")                w.WriteHeader(http.StatusInternalServerError)                json.NewEncoder(w).Encode(ErrorResponse{                    Code:    http.StatusInternalServerError,                    Message: "Internal server error",                })            }        }()        // Call the next handler        next.ServeHTTP(w, r)    })}

This middleware uses defer and recover to capture runtime panics, preventing service crashes while ensuring errors can be formatted and returned.

Helper Function for Actively Returning Errors

Provides utility functions for handlers to easily return unified errors.

func writeError(w http.ResponseWriter, code int, message string) {    w.Header().Set("Content-Type", "application/json")    w.WriteHeader(code)    json.NewEncoder(w).Encode(ErrorResponse{        Code:    code,        Message: message,    })} // Usage in handler func userHandler(w http.ResponseWriter, r *http.Request) {    user, err := getUser(r.Context())    if err != nil {        writeError(w, http.StatusNotFound, "User not found")        return    }    json.NewEncoder(w).Encode(user)}

By encapsulating the writeError function, business logic can quickly return standard errors, reducing duplicate code.

Integration into HTTP Service

Apply the middleware to the router for global error handling.

func main() {    mux := http.NewServeMux()    mux.HandleFunc("/user", userHandler)    handler := ErrorHandlingMiddleware(mux)    http.ListenAndServe(":8080", handler)}

All requests passing through this middleware will be protected by error handling, even unhandled panics will be caught.

That’s basically it. A concise error middleware along with helper functions can provide clear and consistent error output for Go’s HTTP services. It’s not complicated but easy to overlook details, such as setting Content-Type and the correct use of defer.

This concludes the detailed content on Golang HTTP error handling with a unified error response middleware. For more, please follow our public account for other related articles!

Leave a Comment