Documentation
¶
Overview ¶
Package arc helps Go applications route net/http requests without adopting a larger web framework.
The main type is Router. Create one during application startup, register routes and middleware on it, then pass it to http.ListenAndServe or http.Server:
r := arc.New()
r.Get("/users/{id}", func(w http.ResponseWriter, req *http.Request) {
id := arc.Param(req, "id")
fmt.Fprintln(w, id)
})
log.Fatal(http.ListenAndServe(":8080", r))
Handlers are ordinary http.Handler and http.HandlerFunc values. Middleware is the standard net/http wrapper shape, so existing middleware can usually be used directly. Arc focuses on dispatch: method routing, route parameters, middleware groups, subrouters, mounted handlers, host routing, and fallback handlers. It does not provide response rendering, request binding, logging, validation, or other framework features.
Route, subrouter, mount, and host patterns use the github.com/ryanfowler/match grammar. Route, subrouter, and mount path patterns must be absolute paths beginning with /. In paths, {name} captures one non-empty segment and {*name} captures the non-empty remainder of the path. Captured parameters are stored on the request and can be read with Params or Param. Use Router.SetRequestPathValues to also expose them through http.Request.PathValue.
Arc also sets http.Request.Pattern for matched routes, mounted handlers, and method-not-allowed fallbacks. The value is the full path pattern, including subrouter or mount prefixes, but it does not include a matched host pattern. Middleware can read Request.Pattern after Arc has selected the route, mount, or method-not-allowed fallback it wraps. Parent middleware that wraps a host router or subrouter runs before the child router's final path match and should not depend on the child's final pattern. Not-found fallback handlers receive an empty Request.Pattern, even when host or subrouter parameters were captured.
Use SubRouter to group a section of an application behind a shared path prefix, Mount to attach an existing http.Handler below a path, and Host to dispatch different domains or subdomains to different routers.
Dispatch checks host routers first. Inside a host or ordinary router, routes, subrouters, and mounted handlers share one path matcher, so the most specific path wins. A direct route below a subrouter or mounted prefix can handle that path; other paths below the prefix remain owned by the child.
Arc normally matches paths using req.URL.Path as parsed by net/http. When req.URL.RawPath preserves an escaped slash, Arc matches an internal decoded path where the escaped slash stays inside its segment, then restores captured parameters before exposing them. It does not perform net/http.ServeMux path cleaning redirects for dot segments or repeated slashes. GET routes handle HEAD requests by default when no explicit HEAD or any-method route matches; use Router.SetImplicitHead to disable that behavior.
Index ¶
- Variables
- func Param(req *http.Request, name string) string
- type Middleware
- type RequestParams
- type Router
- func (r *Router) Delete(pattern string, h http.HandlerFunc)
- func (r *Router) Get(pattern string, h http.HandlerFunc)
- func (r *Router) Handle(pattern string, h http.Handler)
- func (r *Router) HandleErr(pattern string, h http.Handler) error
- func (r *Router) HandleFunc(pattern string, h http.HandlerFunc)
- func (r *Router) HandleMethod(method, pattern string, h http.Handler)
- func (r *Router) HandleMethodErr(method, pattern string, h http.Handler) error
- func (r *Router) HandleMethodFunc(method, pattern string, h http.HandlerFunc)
- func (r *Router) Head(pattern string, h http.HandlerFunc)
- func (r *Router) Host(pattern string) *Router
- func (r *Router) HostErr(pattern string) (*Router, error)
- func (r *Router) Mount(pattern string, h http.Handler)
- func (r *Router) MountErr(pattern string, h http.Handler) error
- func (r *Router) Options(pattern string, h http.HandlerFunc)
- func (r *Router) Patch(pattern string, h http.HandlerFunc)
- func (r *Router) Post(pattern string, h http.HandlerFunc)
- func (r *Router) Put(pattern string, h http.HandlerFunc)
- func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
- func (r *Router) SetImplicitHead(enabled bool)
- func (r *Router) SetMethodNotAllowed(h http.Handler)
- func (r *Router) SetNotFound(h http.Handler)
- func (r *Router) SetRequestPathValues(enabled bool)
- func (r *Router) SetStrictSlash(strict bool)
- func (r *Router) SubRouter(pattern string) *Router
- func (r *Router) SubRouterErr(pattern string) (*Router, error)
- func (r *Router) Use(mw ...Middleware)
Constants ¶
This section is empty.
Variables ¶
var ErrDuplicateParamName = fmt.Errorf("%w: duplicate parameter names are not allowed within one pattern", match.ErrInvalidParam)
ErrDuplicateParamName reports a single registered pattern that captures the same parameter name more than once.
var ErrInvalidPathPattern = errors.New("path patterns must begin with /")
ErrInvalidPathPattern reports a route, subrouter, or mount path pattern that is not an absolute HTTP path.
Functions ¶
func Param ¶
Param returns one named parameter captured while matching req.
Param returns an empty string when name was not captured. Use Params(req). TryGet when callers need to distinguish a missing parameter from a captured empty string, although arc's underlying matcher captures only non-empty values.
Types ¶
type Middleware ¶
Middleware wraps an HTTP handler on a Router.
Middleware uses the same shape as standard net/http middleware. If a router uses middleware a, b, and c, requests flow through a, then b, then c, then the matched handler or fallback handler.
type RequestParams ¶
RequestParams is the parameter set captured while matching a request.
RequestParams aliases match.Params, so application code can use match's Len, At, Get, TryGet, Seq, AppendTo, and All methods directly.
func Params ¶
func Params(req *http.Request) RequestParams
Params returns the parameters captured while matching req.
The returned value is empty when the request did not match a parameterized host, subrouter, mounted handler, or route. If the same parameter name is captured at multiple levels, the more specific match wins: route parameters override subrouter parameters, and subrouter parameters override host parameters.
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router is an http.Handler that dispatches application requests by host, path, and method.
Build a router during startup by configuring fallback handlers and registering middleware, host routers, subrouters, mounted handlers, and routes. After it is built, pass it to http.Server or http.ListenAndServe.
A Router is safe for concurrent serving after registration is complete. The registration and configuration methods are not safe to call concurrently with ServeHTTP or with other registration and configuration methods.
func New ¶
func New() *Router
New creates a Router with defaults suitable for a typical net/http application.
By default, unmatched requests use http.NotFoundHandler and requests whose path matches a route registered for a different method receive 405 Method Not Allowed. GET routes also handle HEAD requests unless an explicit HEAD or any-method route matches.
Child routers and host routers copy the parent router's current settings when they are created.
func (*Router) Delete ¶
func (r *Router) Delete(pattern string, h http.HandlerFunc)
Delete registers h for DELETE requests matching pattern.
func (*Router) Get ¶
func (r *Router) Get(pattern string, h http.HandlerFunc)
Get registers h for GET requests matching pattern.
By default, the route also handles HEAD requests when no explicit HEAD or any-method route matches. Use Router.SetImplicitHead(false) to require an explicit HEAD route.
func (*Router) Handle ¶
Handle registers h for pattern and lets it handle any request method.
Use Handle for endpoints such as health checks or webhooks where the handler should decide which methods are acceptable. The pattern uses the github.com/ryanfowler/match route grammar; for example, /users/{id} captures one segment and /assets/{*path} captures the remaining path.
Routes, subrouters, and mounted handlers share one path matcher on the same router. The most specific path wins, so a direct route below a mounted prefix, such as /api/healthz when /api is a subrouter or mount, handles that path.
Invalid, duplicate, or ambiguous patterns panic with the error returned by match. Use HandleErr to receive the registration error instead.
func (*Router) HandleErr ¶
HandleErr registers h for pattern, lets it handle any request method, and returns registration errors.
The pattern uses the github.com/ryanfowler/match route grammar. Registration errors include non-absolute path patterns, invalid parameter syntax, duplicate parameter names within the pattern, and route conflicts reported by match. A nil handler is treated as http.NotFoundHandler.
Routes, subrouters, and mounted handlers share one path matcher on the same router. The most specific path wins, so a direct route below a mounted prefix handles that path.
func (*Router) HandleFunc ¶
func (r *Router) HandleFunc(pattern string, h http.HandlerFunc)
HandleFunc registers h for pattern and lets it handle any request method.
HandleFunc is a convenience wrapper around Handle.
func (*Router) HandleMethod ¶
HandleMethod registers h for one HTTP method and pattern.
Use HandleMethod when you have an http.Handler value. For http.HandlerFunc handlers, the method helpers such as Get and Post are usually shorter.
The pattern uses the github.com/ryanfowler/match route grammar. Invalid, duplicate, or ambiguous patterns panic with the error returned by match. Use HandleMethodErr to receive the registration error instead.
func (*Router) HandleMethodErr ¶
HandleMethodErr registers h for one HTTP method and pattern and returns registration errors.
The pattern uses the github.com/ryanfowler/match route grammar. Registration errors include non-absolute path patterns, invalid parameter syntax, duplicate parameter names within the pattern, and route conflicts reported by match. A nil handler is treated as http.NotFoundHandler.
func (*Router) HandleMethodFunc ¶
func (r *Router) HandleMethodFunc(method, pattern string, h http.HandlerFunc)
HandleMethodFunc registers h for one HTTP method and pattern.
HandleMethodFunc is a convenience wrapper around HandleMethod.
func (*Router) Head ¶
func (r *Router) Head(pattern string, h http.HandlerFunc)
Head registers h for HEAD requests matching pattern.
func (*Router) Host ¶
Host registers and returns a child router for requests whose host matches pattern.
Use Host when one application serves different routes for different domains or subdomains. Host patterns use the github.com/ryanfowler/match grammar, for example "api.example.com" or "{tenant}.example.com". Request hosts are matched case-insensitively, a port in Request.Host is ignored, and brackets around IPv6 literals are ignored.
Parameters captured by the host pattern are available to handlers registered on the returned router. If no host pattern matches, dispatch falls through to the parent router's subrouters and routes.
Middleware already registered on the parent wraps the host router. Middleware added to the returned router applies only inside that host router, including host-router fallback handlers. The returned router copies the parent's current strict slash, implicit HEAD, request path value, and fallback handler settings when it is created.
Invalid, duplicate, or ambiguous host patterns panic with the error returned by match. Use HostErr to receive the registration error instead.
func (*Router) HostErr ¶
HostErr registers and returns a child router for requests whose host matches pattern, and returns registration errors.
Host patterns use the github.com/ryanfowler/match grammar. Registration errors include invalid parameter syntax, duplicate parameter names within the pattern, and host conflicts reported by match.
func (*Router) Mount ¶
Mount registers h below pattern and lets that handler own the remaining path.
Use Mount for file servers, another router, or any existing http.Handler that should handle everything below a path. The pattern uses the github.com/ryanfowler/match route grammar. Parameters captured by the mount pattern are available to middleware and the mounted handler.
The mounted handler receives the remaining path after the mount point as req.URL.Path. For example, a handler mounted at /assets receives /app.css for a request to /assets/app.css, while both /assets and /assets/ are dispatched as /. Middleware already registered on the parent sees the original request path and wraps the mounted handler.
Mounted handlers and direct parent routes share one path matcher. The most specific path wins, so a parent route below the mounted prefix, such as /assets/healthz, handles that exact path. Other paths under the mounted prefix are owned by the mounted handler.
Invalid, duplicate, or ambiguous mount patterns panic with the error returned by match. Use MountErr to receive the registration error instead.
func (*Router) MountErr ¶
MountErr registers h below pattern and returns registration errors.
The pattern uses the github.com/ryanfowler/match route grammar. An empty pattern is treated as /. Registration errors include non-absolute path patterns, invalid parameter syntax, duplicate parameter names within the pattern, and mount conflicts reported by match. A nil handler is treated as http.NotFoundHandler.
func (*Router) Options ¶
func (r *Router) Options(pattern string, h http.HandlerFunc)
Options registers h for OPTIONS requests matching pattern.
func (*Router) Patch ¶
func (r *Router) Patch(pattern string, h http.HandlerFunc)
Patch registers h for PATCH requests matching pattern.
func (*Router) Post ¶
func (r *Router) Post(pattern string, h http.HandlerFunc)
Post registers h for POST requests matching pattern.
func (*Router) Put ¶
func (r *Router) Put(pattern string, h http.HandlerFunc)
Put registers h for PUT requests matching pattern.
func (*Router) ServeHTTP ¶
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
ServeHTTP dispatches req to the best matching host router, route, subrouter, or mounted handler.
Dispatch checks host routers first. Inside a host or ordinary router, routes, subrouters, and mounted handlers share one path matcher, so the most specific path wins. A route registered directly on a router can therefore handle a path below a subrouter or mounted prefix; other paths below that prefix are still owned by the child, including not-found and method-not-allowed handling.
Route and subrouter matching uses req.URL.Path unless req.URL.RawPath preserves an escaped slash. In that case, Arc matches an internal decoded path where the escaped slash stays inside its segment and restores captured params before exposing them. Arc does not perform net/http.ServeMux path cleaning redirects.
ServeHTTP satisfies http.Handler. It should usually be called by net/http rather than directly.
func (*Router) SetImplicitHead ¶
SetImplicitHead controls whether HEAD requests may use GET routes when no explicit HEAD or any-method route matches.
Implicit HEAD matching is enabled by default. Explicit HEAD and any-method routes take precedence when present.
func (*Router) SetMethodNotAllowed ¶
SetMethodNotAllowed sets the handler used when a request path matches a route pattern, but the request method was not registered for that pattern.
The handler runs through the router's current middleware stack.
Passing nil leaves the router's existing method-not-allowed handler unchanged.
func (*Router) SetNotFound ¶
SetNotFound sets the application handler used when no host, subrouter, mounted handler, or route matches a request.
The handler runs through the router's current middleware stack.
Passing nil leaves the router's existing not-found handler unchanged.
func (*Router) SetRequestPathValues ¶
SetRequestPathValues controls whether captured parameters are mirrored to http.Request.PathValue.
Request path values are disabled by default. Enable this when middleware or handlers need to read route parameters with req.PathValue instead of arc.Param or arc.Params.
Subrouters and host routers copy this setting when they are created. Later changes on the parent do not affect existing children.
func (*Router) SetStrictSlash ¶
SetStrictSlash controls whether route matching treats a trailing slash as significant.
Strict slash matching is enabled by default. When disabled, a request path ending in "/" may match a route registered without that final slash. Exact route matches still take precedence.
Subrouters and host routers copy this setting when they are created. Later changes on the parent do not affect existing children.
func (*Router) SubRouter ¶
SubRouter registers and returns a child router for an application section mounted at pattern.
Use a subrouter when several routes share a path prefix, middleware, fallback handlers, or slash/method settings. The pattern uses the github.com/ryanfowler/match route grammar. Parameters captured by the mount pattern are available to child middleware and handlers.
The child matches against the remaining path after the mount point. For example, a child mounted at /api matches /users for a request to /api/users, while both /api and /api/ are dispatched to the child's / route. The request URL is not rewritten; middleware and handlers still see the original req.URL.Path.
Subrouters and direct parent routes share one path matcher. The most specific path wins, so a parent route such as /api/healthz handles that exact path even when /api is a subrouter. Other paths under the subrouter prefix are owned by the child, including child not-found and method-not-allowed handling. Register routes such as /api/healthz on the child as /healthz when they should use the child's middleware and fallback settings.
Middleware already registered on the parent wraps the child router. Middleware added to the child applies only inside the child router, including child fallback handlers. The child copies the parent's current strict slash, implicit HEAD, request path value, and fallback handler settings when it is created.
Invalid, duplicate, or ambiguous mount patterns panic with the error returned by match. Use SubRouterErr to receive the registration error instead.
func (*Router) SubRouterErr ¶
SubRouterErr registers and returns a child router mounted at pattern and returns registration errors.
The pattern uses the github.com/ryanfowler/match route grammar. An empty pattern is treated as /. Registration errors include non-absolute path patterns, invalid parameter syntax, duplicate parameter names within the pattern, and mount conflicts reported by match.
func (*Router) Use ¶
func (r *Router) Use(mw ...Middleware)
Use appends middleware to the router.
Middleware applies only to routes, subrouters, host routers, and mounted handlers registered after the call to Use. Fallback handlers use the router's current middleware stack. This lets applications build separate sections of a router with different middleware stacks. Middleware is executed in the order it is added. Use panics if any middleware is nil.