Documentation
¶
Overview ¶
Package httpx provides extended HTTP utilities for Go, extending net/http with error-returning handlers, middleware support, graceful shutdown, and composable mux wrappers.
Error-Returning Handlers ¶
The core feature is handlers that return errors instead of manually writing error responses:
mux := httpx.New()
mux.Route("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) error {
user, err := getUser(r.PathValue("id"))
if err != nil {
return httpx.InternalError(err, "Failed to retrieve user")
}
return httpx.Send(w, user)
})
Errors are automatically converted to JSON responses with appropriate status codes:
- Regular errors: 400 Bad Request
- Internal errors (httpx.InternalError): 500 Internal Server Error (logged server-side)
- HTTP errors (httperrors.HTTPError): Custom status codes and details
Graceful Shutdown ¶
The ListenAndServe function provides automatic graceful shutdown on SIGINT/SIGTERM:
httpx.ListenAndServe(":8080", mux, &httpx.ServerConfig{
ShutdownTimeout: 30 * time.Second,
})
Middleware ¶
Apply middleware to routes using the Use wrapper:
mux := httpx.Use(
http.NewServeMux(),
loggingMiddleware,
authMiddleware,
)
Composable Mux Wrappers ¶
Chain multiple mux wrappers for layered functionality:
mux := httpx.New() mux = httpx.NormalizeTrailingSlash(mux) mux = httpx.Prefix(mux, "/api/v1") mux = httpx.Use(mux, corsMiddleware) mux = httpx.Fallback(mux, customErrorHandler)
Available mux wrappers:
- Prefix: Add common prefix to routes
- Use: Apply middleware
- Fallback: Custom error handling
- NormalizeTrailingSlash: Handle routes with/without trailing slashes
Request and Response Helpers ¶
Simplified JSON encoding and decoding:
// Read request body user, err := httpx.Read[User](r) // Send response httpx.Send(w, user) httpx.SendStatus(w, http.StatusCreated, user)
Subpackages ¶
The httpx module includes specialized subpackages:
- httperrors: Structured HTTP error handling with status codes
- contextkey: Type-safe context key management
- session: Session-based authentication with cookies and flash messages
Index ¶
- func Group(mux ServeMux, prefix string, sub func(Mux))
- func Handler(mux ServeMux, handler func(http.ResponseWriter, *http.Request) error) http.Handler
- func InternalError(err error, message string) error
- func ListenAndServe(addr string, handler http.Handler, config *ServerConfig) error
- func MuxPrefix(mux ServeMux) string
- func Read[T any](r *http.Request) (data T, err error)
- func Send(w http.ResponseWriter, v any) error
- func SendStatus(w http.ResponseWriter, statusCode int, v any) error
- type ErrorHandler
- type HandlerFunc
- type JSON
- type Middleware
- type Mux
- type ServeMux
- type ServerConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Group ¶ added in v0.4.0
Group registers a group of routes by calling sub with a Prefixed mux.
Prefix concatenates the prefix with each registered pattern and registers the resulting pattern on the underlying mux. Any HTTP method specified in the pattern (for example "GET /users") is preserved in the resulting pattern. No other parsing, normalization, or rewriting is performed.
func Handler ¶
Handler converts a handler function that returns an error into an http.Handler. Handler(mux, f) is a http.Handler that calls f. If returned error is non-nil, it handles the error using the error handler extracted from mux. If mux is nil, the default error handler is used.
The default error handler replies to the request with a JSON response of the error message and status code based on error type:
- Regular errors: http.StatusBadRequest (400)
- Internal errors (InternalError): http.StatusInternalServerError (500)
- HTTP errors (httperrors.HTTPError): Custom status codes and details
func InternalError ¶
InternalError wraps an error with a user-friendly message for client responses. If message is empty, it defaults to "Something went wrong".
When used with the default error handler, it logs the underlying error (with request method and path) while returning only the user-friendly message to the client. This prevents internal implementation details from leaking while maintaining debug visibility.
user, err := getUser(id)
if err != nil {
// Logs: "[ERROR] GET /api/users/123: Failed to retrieve user: sql: no rows in result set"
// Returns to client: {"error": "Failed to retrieve user"}
return httpx.InternalError(err, "Failed to retrieve user")
}
func ListenAndServe ¶
func ListenAndServe(addr string, handler http.Handler, config *ServerConfig) error
ListenAndServe starts an HTTP server with graceful shutdown. It listens on the TCP network address addr and calls Serve with handler to handle requests.
If handler is nil, http.DefaultServeMux is used. If config is nil, default configuration is used (default server, 30s shutdown timeout).
The server will shutdown gracefully when it receives SIGINT or SIGTERM signals. During shutdown, the server will stop accepting new connections and wait for existing connections to finish, up to config.ShutdownTimeout.
ListenAndServe returns when the server has shut down completely. If the server fails to start, it returns the error immediately. If shutdown completes successfully, it returns nil. If shutdown exceeds the timeout, it returns context.DeadlineExceeded.
func MuxPrefix ¶ added in v0.4.0
MuxPrefix returns the cumulative path prefix accumulated by any Prefix mux types in the chain. Returns an empty string if no prefix is found.
func Read ¶
Read decodes the JSON request body into T. Returns an error if the body is malformed JSON, or has wrong Content-Type. If Content-Type header is present, it must be "application/json" (or with charset).
user, err := httpx.Read[User](r)
if err != nil {
return httperrors.New(err.Error(), http.StatusBadRequest)
}
func Send ¶
func Send(w http.ResponseWriter, v any) error
Send encodes v as JSON and writes it to the response. It returns an error if encoding fails.
return httpx.Send(w, user)
func SendStatus ¶
func SendStatus(w http.ResponseWriter, statusCode int, v any) error
SendStatus encodes v as JSON and writes it to the response with the given status code. It returns an error if encoding fails.
return httpx.SendStatus(w, http.StatusCreated, user)
Types ¶
type ErrorHandler ¶
type ErrorHandler interface {
HandleError(http.ResponseWriter, *http.Request, error)
}
func MuxErrorHandler ¶
func MuxErrorHandler(mux ServeMux) ErrorHandler
MuxErrorHandler returns the error handler for mux. If mux is nil or does not implement the ErrorHandler interface, the default error handler is returned.
The default error handler replies to the request with a JSON response of the error message and status code based on error type:
- Regular errors: http.StatusBadRequest (400)
- Internal errors (InternalError): http.StatusInternalServerError (500)
- HTTP errors (httperrors.HTTPError): Custom status codes and details
type HandlerFunc ¶
type HandlerFunc func(http.ResponseWriter, *http.Request) error
HandlerFunc allows the use of handler functions that return an error as HTTP handlers. HandlerFunc(f) is a http.Handler that calls f. If returned error is non-nil, it handles the error using the default error handler.
The default error handler replies to the request with a JSON response of the error message and status code based on error type:
- Regular errors: http.StatusBadRequest (400)
- Internal errors (InternalError): http.StatusInternalServerError (500)
- HTTP errors (httperrors.HTTPError): Custom status codes and details
func (HandlerFunc) ServeHTTP ¶
func (f HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request)
type Middleware ¶
Middleware is a function that accepts a handler and returns another handler. Middlewares can decide to call or not to call the handler and they can run before or after the handler.
type Mux ¶
type Mux interface {
ServeMux
Mux() ServeMux
Route(pattern string, handler func(http.ResponseWriter, *http.Request) error)
}
Mux is a specialized mux that can register routes with handlers that return an error.
func Fallback ¶
Fallback returns a Mux which executes errorHandler when the handler returns a non-nil error.
func NormalizeTrailingSlash ¶
NormalizeTrailingSlash returns a Mux that registers an exact trailing slash variant for each base pattern, so both "/path" and "/path/" match the same handler. Patterns already ending with "/" or "/{$}" are unchanged.
By default, Go's mux treats these pattern types as follows:
mux := http.NewServeMux()
mux.HandleFunc("/api", h) // base: exact match only
→ GET /api → 200
→ GET /api/ → 404
→ GET /api/nested → 404
mux.HandleFunc("/api/", h) // subtree: matches /api/ and all paths below
→ GET /api → 301 redirect to /api/
→ GET /api/ → 200
→ GET /api/nested → 200
mux.HandleFunc("/api/{$}", h) // exact trailing slash: matches /api/ only
→ GET /api → 301 redirect to /api/
→ GET /api/ → 200
→ GET /api/nested → 404
To support both "/api" and "/api/", you would have to register "/api/{$}" manually and still accept that "/api" redirects to "/api/" instead of being served directly. NormalizeTrailingSlash solves this by registering both "/api" and "/api/{$}":
mux := httpx.NormalizeTrailingSlash(mux)
mux.HandleFunc("/api", h) // registers both /api and /api/{$}
→ GET /api → 200
→ GET /api/ → 200
→ GET /api/nested → 404
func Prefix ¶
Prefix returns a Mux that registers routes under the given prefix.
Prefix concatenates the prefix with each registered pattern and registers the resulting pattern on the underlying mux. Any HTTP method specified in the pattern (for example "GET /users") is preserved in the resulting pattern. No other parsing, normalization, or rewriting is performed.
func Use ¶
func Use(mux ServeMux, middlewares ...Middleware) Mux
Use returns a Mux which applies middlewares to the handler. Use with an empty middlewares list can be used to convert a *http.ServeMux to a Mux.
type ServeMux ¶
type ServeMux interface {
http.Handler
Handle(pattern string, handler http.Handler)
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
}
ServeMux is the generic interface for route registering mux.
type ServerConfig ¶
type ServerConfig struct {
// Server is the HTTP server configuration.
// If nil, a default http.Server will be used.
Server *http.Server
// ShutdownTimeout is the maximum duration to wait for graceful shutdown.
// Default: 30 seconds.
ShutdownTimeout time.Duration
}
ServerConfig configures the HTTP server and graceful shutdown.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package contextkey provides type-safe context key management using Go generics.
|
Package contextkey provides type-safe context key management using Go generics. |
|
Package httperrors provides a structured way to handle HTTP errors with status codes and details.
|
Package httperrors provides a structured way to handle HTTP errors with status codes and details. |
|
Package openapi builds an OpenAPI document alongside httpx route registration.
|
Package openapi builds an OpenAPI document alongside httpx route registration. |
|
Package session implements session based authentication type-safe cookies, and flash messages.
|
Package session implements session based authentication type-safe cookies, and flash messages. |