Documentation
¶
Overview ¶
Package router provides a lightweight, JSON-centric wrapper around Go's native http.ServeMux.
It simplifies building JSON APIs by offering a consolidated "Exchange" object for handling requests and responses, standardized error formatting, and a middleware chaining mechanism.
Basic Usage:
// 1. Setup the router with options
logger := log.New()
r := router.New(
router.WithLogger(logger),
router.WithMiddleware(middleware.Log(logger)),
)
// 2. Define a handler
// You can use a closure, or a struct that satisfies the Handler interface.
r.HandleFunc("POST /users", func(e *router.Exchange) error {
var req CreateUserRequest
// BindJSON enforces Content-Type and parses the body.
// It returns a specific *router.Error type if validation fails.
if err := e.BindJSON(&req); err != nil {
return err
}
// ... Logic to save user ...
// Return JSON response
return e.JSON(http.StatusCreated, UserResponse{ID: "123"})
})
// 3. Start the server
http.ListenAndServe(":8080", r)
Index ¶
- Constants
- type Error
- type ErrorHandler
- type Exchange
- func (e *Exchange) BindJSON(v any) *Error
- func (e *Exchange) Context() context.Context
- func (e *Exchange) Form(code int, v url.Values) error
- func (e *Exchange) GetHeader(key string) string
- func (e *Exchange) Header() http.Header
- func (e *Exchange) JSON(code int, v any) error
- func (e *Exchange) Method() string
- func (e *Exchange) NoContent()
- func (e *Exchange) Param(name string) string
- func (e *Exchange) Path() string
- func (e *Exchange) Query() url.Values
- func (e *Exchange) ReadForm() (url.Values, *Error)
- func (e *Exchange) Redirect(url string, code int) error
- func (e *Exchange) RedirectTo(base string, params url.Values, code int) error
- func (e *Exchange) SetHeader(key, value string)
- func (e *Exchange) Status(code int)
- func (e *Exchange) URL() *url.URL
- type Handler
- type HandlerFunc
- type Option
- type ResponseWriter
- type Router
- func (r *Router) Handle(pattern string, handler Handler, mws ...middleware.Pipe)
- func (r *Router) HandleFunc(pattern string, fn func(*Exchange) error, mws ...middleware.Pipe)
- func (r *Router) Mount(pattern string, handler http.Handler)
- func (r *Router) ServeHTTP(res http.ResponseWriter, req *http.Request)
Constants ¶
const ( // ReasonWrongType indicates that the request had an unsupported content type. ReasonWrongType = "wrong_type" // ReasonEmptyBody indicates that the request body was empty. ReasonEmptyBody = "empty_body" // ReasonParseJSON indicates that there was an error parsing the JSON body. ReasonParseJSON = "parse_json" // ReasonParseForm indicates that there was an error parsing form data. ReasonParseForm = "parse_form" // ReasonServerError indicates that an unexpected internal error occurred. ReasonServerError = "server_error" )
Standard error reasons used for machine-readable error codes.
const ( // MediaTypeJSON is the media type for JSON content. MediaTypeJSON = "application/json" // MediaTypeForm is the media type for URL-encoded form data. MediaTypeForm = "application/x-www-form-urlencoded" )
Standard media types used in the Content-Type header.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Error ¶
type Error struct {
// Status is the HTTP status code (e.g., 400, 404, 500).
Status int `json:"status"`
// Reason is a short string identifying the error type (e.g.,
// "invalid_input").
Reason string `json:"reason"`
// Description is a human-readable explanation of the error cause.
Description string `json:"description"`
// ID is a unique identifier of the specific occurrence for tracing purposes
// (optional).
ID string `json:"id,omitempty"`
// Context contains arbitrary additional data about the error, such as
// validation fields.
Context map[string]any `json:"context,omitempty"`
// Cause is the underlying error that triggered this error (if any).
// It is excluded from JSON serialization to prevent leaking internal details.
Cause error `json:"-"`
}
Error describes the standardized shape of API errors returned to clients.
Handlers can return this struct directly to control the HTTP status code and error details. If a handler returns a standard Go error, the Router will wrap it in a generic internal server error.
type ErrorHandler ¶ added in v1.1.8
ErrorHandler defines a function that handles errors returned by routes.
type Exchange ¶
type Exchange struct {
// R is the incoming HTTP request.
R *http.Request
// W is a writer for the outgoing HTTP response.
W ResponseWriter
// contains filtered or unexported fields
}
Exchange acts as a context object for a single HTTP request/response cycle.
It wraps the underlying *http.Request and http.ResponseWriter to provide convenient helper methods for common API tasks, such as parsing JSON, reading parameters, and writing structured responses.
func (*Exchange) BindJSON ¶
BindJSON decodes the request body into v.
This method enforces strict API hygiene: 1. It verifies that the media type is "application/json". 2. It checks that the payload is not empty. 3. It unmarshals the JSON.
If any of these checks fail, it returns a structured error that handlers can return directly.
func (*Exchange) Context ¶
Context returns the request's context. This is commonly used for cancellation signals and request scoping.
func (*Exchange) Form ¶ added in v1.1.0
Form writes the values as URL-encoded form data with the given status code.
It automatically sets the Content-Type header to MediaTypeForm if it has not already been set. When encoding fails, an error is returned.
func (*Exchange) JSON ¶
JSON encodes v as JSON and writes it to the response with the given HTTP status code.
It automatically sets the Content-Type header to MediaTypeJSON if it has not already been set. When encoding fails, an error is returned.
func (*Exchange) NoContent ¶ added in v1.1.8
func (e *Exchange) NoContent()
NoContent sends a HTTP 204 No Content response.
func (*Exchange) Param ¶
Param retrieves a path parameter by name.
This relies on the routing pattern (e.g., "GET /users/{id}"). If the parameter does not exist, it returns an empty string.
func (*Exchange) Query ¶
Query parses the URL query parameters of the request. Malformed pairs will be silently discarded.
func (*Exchange) ReadForm ¶ added in v1.1.0
ReadForm parses the request body as URL-encoded form data and returns the values.
Unlike the standard http.Request.FormValue, this strictly accesses the PostForm (body) only, ignoring URL query parameters. This is crucial for security protocols like OAuth to prevent query parameter injection.
func (*Exchange) Redirect ¶
Redirect replies to the request with a redirect to url, which may be a path relative to the request path.
Any non-ASCII characters in url will be percent-encoded, but existing percent encodings will not be changed. The provided code should be in the 3xx range.
func (*Exchange) RedirectTo ¶ added in v1.1.0
RedirectTo constructs a URL by merging the base URL with the provided query parameters and redirects the client.
This is particularly useful for callbacks.
func (*Exchange) Status ¶
Status sends an HTTP response header with the provided status code.
Note: Calling this method commits the response headers. You should not call this method directly if you intend to write a body later (e.g., using JSON() or Form()), as those methods will set the status code themselves. It is primarily used for empty responses like HTTP 204 (No Content).
type Handler ¶
type Handler interface {
// ServeHTTP processes an HTTP request encapsulated in the Exchange object.
ServeHTTP(e *Exchange) error
}
Handler defines the interface for HTTP request handlers used by the Router.
This interface allows using struct-based handlers (useful for dependency injection) in addition to simple functions.
type HandlerFunc ¶
HandlerFunc defines the function signature for HTTP request handlers.
func (HandlerFunc) ServeHTTP ¶
func (f HandlerFunc) ServeHTTP(e *Exchange) error
ServeHTTP satisfies the Handler interface, allowing HandlerFunc to be used wherever a Handler is expected.
type Option ¶
type Option func(*Router)
Option defines a functional configuration option for the Router.
func WithErrorHandler ¶ added in v1.1.8
func WithErrorHandler(h ErrorHandler) Option
WithErrorHandler sets a custom error handler. This allows you to override the default JSON error formatting.
func WithJSONOptions ¶ added in v1.1.8
WithJSONOptions sets custom JSON options for the Router. They configure both, marshaling and unmarshaling operations.
func WithLogger ¶
WithLogger updates the default error handler to use the given logger. If not set, the Router defaults to using slog.Default(). A nil value will be ignored.
func WithMaxBodySize ¶ added in v1.1.8
WithMaxBodySize sets the maximum allowed size for request bodies. Defaults to 0 (unlimited), but typically should be set (e.g., 1MB).
func WithMiddleware ¶
func WithMiddleware(pipes ...middleware.Pipe) Option
WithMiddleware adds global middleware pipes to the Router. These pipes are applied to every route registered with the Router.
type ResponseWriter ¶ added in v1.1.8
type ResponseWriter interface {
http.ResponseWriter
// Status returns the HTTP status code written, or 0 if not written yet.
Status() int
// Closed reports whether the headers have already been written.
// This indicates that the response is committed.
Closed() bool
// Unwrap returns the underlying http.ResponseWriter.
// This allows [http.ResponseController] to access features like Flush(),
// Hijack(), and SetReadDeadline().
Unwrap() http.ResponseWriter
}
ResponseWriter extends the standard http.ResponseWriter with introspection capabilities.
It allows handlers and middleware to check if the response headers have already been written, which is crucial for robust error handling.
func NewResponseWriter ¶ added in v1.1.8
func NewResponseWriter(w http.ResponseWriter) ResponseWriter
NewResponseWriter wraps an http.ResponseWriter into a ResponseWriter.
type Router ¶
type Router struct {
// Mux is the underlying [http.ServeMux]. It is exposed to allow direct
// usage with [http.ListenAndServe].
Mux *http.ServeMux
// contains filtered or unexported fields
}
Router represents an HTTP request router with middleware support.
func (*Router) Handle ¶
func (r *Router) Handle( pattern string, handler Handler, mws ...middleware.Pipe, )
Handle registers a new route with the given pattern, handler, and optional middleware pipes.
The pattern string must follow Go 1.22+ syntax (e.g., "GET /users/{id}").
The handler is wrapped with the Router's global middleware and any local middleware provided for this specific route.
func (*Router) HandleFunc ¶
HandleFunc is a convenience wrapper for Handle that accepts a function instead of a Handler interface.
func (*Router) Mount ¶
Mount registers a standard http.Handler (like http.FileServer) under a pattern.
The handler will still be wrapped by the Router's global middleware, ensuring logging/auth logic applies to these routes as well.
func (*Router) ServeHTTP ¶
func (r *Router) ServeHTTP(res http.ResponseWriter, req *http.Request)
ServeHTTP satisfies the http.Handler interface, allowing the Router to be used directly with HTTP servers. It delegates request handling to the underlying http.ServeMux.