njia

package module
v0.0.1-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

Njia

njia (Swahili: path, way) is a zero-dependency HTTP router for Go.

It has two public surfaces:

Surface Import path Purpose
Native API github.com/jkaninda/njia The real product. Fast, introspectable, allocation-conscious.
Compat API github.com/jkaninda/njia/muxcompat Drop-in replacement for github.com/gorilla/mux. A migration bridge.

The main module has zero require entries and imports nothing outside the standard library. gorilla/mux appears only in a separate, test-only module under internal/difftest, which is how behavioral parity is verified.


Native API

r := njia.New()

r.GET("/healthz", healthHandler)
r.GET("/users/{id}", getUser)
r.GET("/files/{rest...}", serveFile)

api := r.Group("/api/v1", authMiddleware, rateLimitMiddleware)
api.POST("/orders", createOrder, njia.WithName("createOrder"))

log.Fatal(http.ListenAndServe(":8080", r))

Read a parameter without building a map:

func getUser(w http.ResponseWriter, r *http.Request) {
    id := njia.Param(r, "id")   // no map, no allocation
    ...
}
Registration returns errors, never panics
if err := r.GET("/users/{id", handler); err != nil {
    // njia: route GET "/users/{id": njia: malformed route pattern: ...
}

Every failure is a typed sentinel (ErrBadPattern, ErrDuplicateRoute, ErrParamConflict, ErrCatchAllPosition, ErrBadHost, …) wrapped in a *RouteError that names the offending method and pattern. This matters for gateways that build routes from user-supplied configuration: a bad entry is rejected, not fatal.

Parameters

{id} matches any single non-empty segment, and {rest...} absorbs the remainder of the path including slashes. A placeholder carries a name and nothing else.

{id:constraint} is rejected rather than ignored, so a pattern that looks like it filters values can never silently match everything:

err := r.GET("/users/{id:int}", getUser)
// njia: route GET "/users/{id:int}": njia: malformed route pattern:
// "{id:int}" constrains "id", which this router does not support; write {id}

Validate values in the handler, where a bad one can produce a useful 400 rather than falling through to a 404. muxcompat accepts gorilla's {id:[0-9]+} regular expressions if you need matching to depend on the value.

Routes are matched most-specific-first: a static segment beats a wildcard, which beats a catch-all, resolved position by position from the left. Matching backtracks, so a static branch that dead-ends never hides a wildcard that would have matched.

Host matching
gw := r.Host("api.example.com", "*.api.example.com")
gw.GET("/orders/{id}", getOrder)

r.Host("{tenant}.app.example.com").GET("/dashboard", dashboard)  // njia.Param(req, "tenant")
r.GET("/healthz", health)                                        // every host

Accepted patterns, most specific first:

Pattern Matches
api.example.com:8443 exactly this host on this port
api.example.com exactly this host, any port
{sub}.example.com exactly one leading label, captured as sub
*.example.com one or more leading labels
{sub...}.example.com one or more leading labels, captured
{host...} any host, captured whole
* any host

Matching is case-insensitive and ignores a trailing dot, so API.Example.COM. and api.example.com are the same name. A pattern that names a port only matches requests carrying that port; one that does not, ignores the port entirely. WithHost(...) restricts a single route and overrides its group. ValidateHost checks a pattern without registering anything, so a gateway can reject a bad configuration entry before building a table.

Precedence. Path specificity is decided first, host specificity second, registration order last. A global /healthz therefore stays reachable underneath a per-host catch-all proxy route — which is exactly how a gateway needs it:

r.GET("/healthz", health)                                  // wins on every host
r.Host("okapi.example.com").GET("/{rest...}", proxyOkapi)  // everything else

Within one path pattern, hosts are consulted from most to least specific, and a variant that does not serve the request's method falls through to a less specific one. A path that exists but not on the requested host is a 404; a path that exists on that host but not for that method is a 405, and the Allow header only lists methods that host actually serves.

Exact hosts are indexed by name, so a gateway with a thousand virtual hosts costs one map lookup, not a thousand comparisons. Tables that use no host constraint at all never read the request's host — the feature costs them nothing.

Introspection
for _, ri := range r.Routes() {
    fmt.Println(ri.Method, ri.PathTemplate, ri.Params, ri.Meta)
}

RouteInfo carries the template as written, the host patterns it answers on, each parameter's name and position (host parameters are reported first, marked InHost), the handler, and any annotations attached with WithMeta. An OpenAPI generator needs nothing else — in particular it never has to reconstruct a template from a compiled regular expression. Value types are not part of the pattern, so a generator carries schema information in WithMeta.

Atomic hot reload
err := r.Swap(func(b *njia.Builder) error {
    for _, route := range configFromYAML() {
        if err := b.Handle(route.Method, route.Path, route.Handler); err != nil {
            return err
        }
    }
    return nil
})

The new table is built and fully validated off to the side. On any error the running table is untouched. On success it is installed with a single atomic pointer store; in-flight requests finish against the old table and there is no lock anywhere on the request path.

Middleware ordering

Router middleware is outermost, then each enclosing group's middleware from outer to inner, then the route's own middleware, then the handler. This is tested, not merely documented.


Compat API

gorilla/mux was archived in December 2022 and has been effectively dormant since. muxcompat lets a project move off it with an import rewrite:

-import "github.com/gorilla/mux"
+import mux "github.com/jkaninda/njia/muxcompat"

Nothing else changes. The package reproduces gorilla's exported API and its observable behavior — route ordering, strict-slash redirects, path cleaning, MatchErr propagation, subrouter matcher inheritance, reverse URL building, Walk, CORSMethodMiddleware — including the corners that are surprising:

  • Queries with an odd number of arguments records an error and returns nil, so chaining onto it panics. Reproduced, because callers may depend on it.
  • A host template without a port has the request's port stripped at the first colon; a host template with a port does not.
  • Methods() with no arguments matches nothing.
  • Queries("k", "") matches the key with any value.
  • A capturing group inside a variable pattern panics at registration.

Where njia deliberately differs from gorilla, it is only by being more robust: a handful of inputs make gorilla fault at runtime (nil pointer dereference, slice bounds out of range) and njia serves them instead. The differential harness treats a gorilla runtime fault as a gorilla bug and only requires that njia does not fault differently.

Not the destination

muxcompat is a bridge. It stays published for anyone migrating off gorilla, but new features go into the native API. Nothing in muxcompat imports the root njia package; the two surfaces evolve independently on top of shared internal/ packages.


How correctness is established

Behavior is never written from memory or from documentation prose. Every gorilla behavior njia reproduces was first observed by running real gorilla.

  • internal/difftest drives both engines with identical route tables and identical requests, then compares the matched route, captured variables, response status, redirect location, response body, match error, per-route build errors and panic behavior.
  • internal/difftest/vendored is gorilla's own test suite, adapted to target muxcompat. It carries gorilla's BSD-3-Clause header; only test cases and fixtures were taken, never implementation code. OMITTED.md records the handful of white-box tests that could not be expressed through the exported API.
  • A property-based generator builds random route tables and request paths covering static paths, wildcards, regular expression constraints, prefixes, host templates, methods, queries, headers, schemes, subrouters, overlapping routes, percent-encoded and empty and dot segments, very long paths and unicode. CI runs 200,000 generated cases per commit.
  • Real route tables extracted from Okapi and Goma Gateway are replayed against both engines under five router configurations. This is the migration acceptance gate.
  • The lookup index is proved inert: muxcompat can be forced onto the plain ordered scan, and a test drives every table both ways and requires the two to agree on every observable field.
  • Host routing is checked against a reference model: a deliberately naive resolver that scans every route and sorts, run against 400 generated route tables over every combination of 11 hosts, 13 paths and 5 methods — about 286,000 comparisons. It is what caught the specificity bug that let /api/{rest...} shadow /api.

Performance

Measured with internal/difftest/bench, which compares gorilla/mux, the standard library ServeMux, chi and both njia surfaces at 10, 100 and 1000 routes.

The native router matches with a segment-indexed prefix tree and a direct map lookup for fully static patterns. muxcompat splits its table: routes that are static segments plus plain {name} wildcards with at most a method filter go into the tree, everything else stays on an ordered scan, and registration sequence numbers are compared across the two so gorilla's first-registered-wins ordering is preserved exactly.

Run the grid yourself:

cd internal/difftest
go test -run '^$' -bench . -benchmem -benchtime=500ms -count=6 ./bench/...
go run golang.org/x/perf/cmd/benchstat@latest -col /size <output>

-count=6 and benchstat are not optional ceremony: a single pass is noisy enough that machine drift reads as a real regression. When comparing two revisions, check the stdlib and chi rows first — their code does not change between njia revisions, so if they moved, the machine moved and nothing can be attributed to njia.

The grid also contains TestGridSanity and TestHostGridSanity, which assert that every engine really returns 200/404/405 for the scenarios it is benchmarked on, so no router can look fast by quietly 404ing.


Licensing

njia is Apache-2.0. Test cases and fixtures adapted from gorilla/mux are BSD-3-Clause and retain their original copyright header; see NOTICE.

Documentation

Overview

Package njia is a zero-dependency HTTP router for Go.

It routes with a segment-indexed prefix tree, captures path parameters without building a map, and reports its own route table so that documentation can be generated from the routes themselves rather than reconstructed from compiled regular expressions.

r := njia.New()
r.GET("/users/{id}", http.HandlerFunc(getUser))

api := r.Group("/api/v1", authMiddleware)
api.GET("/orders/{id}", http.HandlerFunc(getOrder))

Registration returns an error instead of panicking, and Swap replaces the whole route table atomically after validating it, so a process that builds routes from user-supplied configuration can reload without ever going down.

Package github.com/jkaninda/njia/muxcompat is a separate, drop-in replacement for github.com/gorilla/mux, for projects migrating away from it.

Index

Constants

View Source
const AnyHost = "*"

AnyHost is the host pattern that matches every request. Writing it out is equivalent to registering a route with no host constraint at all, and it exists so that a configuration file can express "any host" explicitly.

Variables

View Source
var (
	// ErrBadPattern reports a template that could not be parsed, such as one
	// with unbalanced braces or an empty variable name.
	ErrBadPattern = errors.New("njia: malformed route pattern")
	// ErrNoLeadingSlash reports a pattern that does not start with a slash.
	ErrNoLeadingSlash = errors.New("njia: route pattern must start with a slash")
	// ErrDuplicateRoute reports a method and pattern pair that is already
	// registered.
	ErrDuplicateRoute = errors.New("njia: duplicate route")
	// ErrParamConflict reports two routes that put differently named
	// parameters with the same constraint at the same position.
	ErrParamConflict = errors.New("njia: conflicting parameter name")
	// ErrCatchAllPosition reports a catch-all parameter that is not the last
	// segment of the pattern.
	ErrCatchAllPosition = errors.New("njia: catch-all parameter must be last")
	// ErrDuplicateName reports a route name that is already in use.
	ErrDuplicateName = errors.New("njia: duplicate route name")
	// ErrNoHandler reports a route registered without a handler.
	ErrNoHandler = errors.New("njia: route has no handler")
	// ErrEmptyMethod reports a route registered without an HTTP method.
	ErrEmptyMethod = errors.New("njia: route has no method")
	// ErrBadHost reports a host pattern that could not be parsed.
	ErrBadHost = errors.New("njia: malformed host pattern")
)

Errors reported by route registration. Every registration failure is one of these, wrapped with context; nothing in this package panics.

Functions

func NumParams

func NumParams(r *http.Request) int

NumParams returns how many path parameters the matched route captured.

func Param

func Param(r *http.Request, name string) string

Param returns the value of the named path parameter, or the empty string if the request has no such parameter.

It builds no map and reads no more than the parameters the matched route declared.

func ParamAt

func ParamAt(r *http.Request, i int) (name, value string, ok bool)

ParamAt returns the i'th path parameter in pattern order. It reports false when i is out of range.

func ParamMap

func ParamMap(r *http.Request) map[string]string

ParamMap returns the captured parameters as a map. It allocates, and exists for callers that need the shape gorilla's Vars returned.

func SetParams

func SetParams(r *http.Request, params ...PathParam) *http.Request

SetParams attaches path parameters to a request. It is intended for tests that invoke a handler directly.

func ValidateHost

func ValidateHost(pattern string) error

ValidateHost reports whether a host pattern is well formed, without registering anything. A gateway that builds its route table from user configuration can use it to reject a bad entry early, with the same error it would get from registration.

Accepted forms, in decreasing specificity:

api.example.com          exactly this host
api.example.com:8443     exactly this host on this port
{sub}.example.com        exactly one leading label, captured as "sub"
*.example.com            one or more leading labels
{sub...}.example.com     one or more leading labels, captured as "sub"
{host...}                any host, captured whole
*                        any host

Matching is case-insensitive and ignores a trailing dot. A pattern that names a port only matches requests carrying that port; a pattern that does not accepts any port.

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder accumulates a route table. It is what Swap hands to its callback, and it is also the object a Router registers into.

Every registration is validated as it happens, so an invalid table is rejected before it can be installed.

func NewBuilder

func NewBuilder() *Builder

NewBuilder returns an empty builder. A table can be assembled and fully validated with one, then installed on a router with Swap.

func (*Builder) DELETE

func (b *Builder) DELETE(pattern string, h http.Handler, opts ...RouteOption) error

DELETE registers a handler for DELETE requests.

func (*Builder) Err

func (b *Builder) Err() error

Err returns the first registration error recorded on the builder, so that a caller which ignored individual return values can still check the table as a whole.

func (*Builder) Errs

func (b *Builder) Errs() []error

Errs returns every registration error recorded on the builder.

func (*Builder) GET

func (b *Builder) GET(pattern string, h http.Handler, opts ...RouteOption) error

GET registers a handler for GET requests.

func (*Builder) Group

func (b *Builder) Group(prefix string, mw ...Middleware) *Group

Group returns a group rooted at the builder.

func (*Builder) HEAD

func (b *Builder) HEAD(pattern string, h http.Handler, opts ...RouteOption) error

HEAD registers a handler for HEAD requests.

func (*Builder) Handle

func (b *Builder) Handle(method, pattern string, h http.Handler, opts ...RouteOption) error

Handle registers a handler for a method and pattern.

func (*Builder) HandleFunc

func (b *Builder) HandleFunc(method, pattern string, h http.HandlerFunc, opts ...RouteOption) error

HandleFunc registers a handler function for a method and pattern.

func (*Builder) Host

func (b *Builder) Host(patterns ...string) *Group

Host returns a group rooted at the builder whose routes only answer on the given host patterns.

func (*Builder) OPTIONS

func (b *Builder) OPTIONS(pattern string, h http.Handler, opts ...RouteOption) error

OPTIONS registers a handler for OPTIONS requests.

func (*Builder) PATCH

func (b *Builder) PATCH(pattern string, h http.Handler, opts ...RouteOption) error

PATCH registers a handler for PATCH requests.

func (*Builder) POST

func (b *Builder) POST(pattern string, h http.Handler, opts ...RouteOption) error

POST registers a handler for POST requests.

func (*Builder) PUT

func (b *Builder) PUT(pattern string, h http.Handler, opts ...RouteOption) error

PUT registers a handler for PUT requests.

func (*Builder) Use

func (b *Builder) Use(mw ...Middleware)

Use appends router-level middleware, applied outermost first to every route in the table.

type Group

type Group struct {
	// contains filtered or unexported fields
}

Group is a path prefix and a middleware chain that routes are registered against.

Middleware ordering is fixed and tested: router-level middleware is outermost, then each enclosing group's middleware from outer to inner, then the route's own middleware, then the handler.

func (*Group) DELETE

func (g *Group) DELETE(pattern string, h http.Handler, opts ...RouteOption) error

DELETE registers a handler for DELETE requests.

func (*Group) GET

func (g *Group) GET(pattern string, h http.Handler, opts ...RouteOption) error

GET registers a handler for GET requests.

func (*Group) Group

func (g *Group) Group(prefix string, mw ...Middleware) *Group

Group returns a nested group.

func (*Group) HEAD

func (g *Group) HEAD(pattern string, h http.Handler, opts ...RouteOption) error

HEAD registers a handler for HEAD requests.

func (*Group) Handle

func (g *Group) Handle(method, pattern string, h http.Handler, opts ...RouteOption) error

Handle registers a handler for a method and pattern within the group.

func (*Group) HandleFunc

func (g *Group) HandleFunc(method, pattern string, h http.HandlerFunc, opts ...RouteOption) error

HandleFunc registers a handler function for a method and pattern.

func (*Group) Host

func (g *Group) Host(patterns ...string) *Group

Host returns a group whose routes only answer on the given host patterns.

The patterns replace, rather than narrow, any host constraint the group already carried: a nested Host call declares outright which hosts its subtree serves. A route matches when any one of the patterns matches.

gw := r.Host("api.example.com", "*.api.example.com")
gw.GET("/orders/{id}", getOrder)

See ParseHostPattern for the accepted forms.

func (*Group) Hosts

func (g *Group) Hosts() []string

Hosts returns the host patterns the group restricts its routes to.

func (*Group) OPTIONS

func (g *Group) OPTIONS(pattern string, h http.Handler, opts ...RouteOption) error

OPTIONS registers a handler for OPTIONS requests.

func (*Group) PATCH

func (g *Group) PATCH(pattern string, h http.Handler, opts ...RouteOption) error

PATCH registers a handler for PATCH requests.

func (*Group) POST

func (g *Group) POST(pattern string, h http.Handler, opts ...RouteOption) error

POST registers a handler for POST requests.

func (*Group) PUT

func (g *Group) PUT(pattern string, h http.Handler, opts ...RouteOption) error

PUT registers a handler for PUT requests.

func (*Group) Prefix

func (g *Group) Prefix() string

Prefix returns the group's accumulated path prefix.

func (*Group) Use

func (g *Group) Use(mw ...Middleware)

Use appends middleware to this group only.

type Middleware

type Middleware func(http.Handler) http.Handler

Middleware wraps a handler, returning the handler to invoke in its place.

type ParamInfo

type ParamInfo struct {
	// Name is the parameter name.
	Name string
	// Position is the index of the segment the parameter occupies, counting
	// from zero after the leading slash.
	Position int
	// CatchAll reports whether the parameter absorbs the remainder of the
	// path, including slashes.
	CatchAll bool
	// InHost reports that the parameter is captured from the request host
	// rather than from its path. A host parameter is always reported first and
	// has a Position of -1.
	InHost bool
}

ParamInfo describes a parameter declared by a route pattern.

type PathParam

type PathParam struct {
	// Name is the parameter name from the route pattern.
	Name string
	// Value is the text captured from the request path.
	Value string
}

PathParam is a captured path parameter.

func AppendParams

func AppendParams(r *http.Request, dst []PathParam) []PathParam

AppendParams appends every captured parameter to dst and returns the extended slice. It is the allocation-free way to enumerate parameters.

type Route

type Route struct {
	// contains filtered or unexported fields
}

Route is a registered method and pattern pair together with the handler that serves it.

func RouteOf

func RouteOf(r *http.Request) *Route

RouteOf returns the route that matched the request, or nil. A static route is reported even though it attaches no parameters.

func (*Route) Handler

func (r *Route) Handler() http.Handler

Handler returns the handler the route was registered with, before middleware.

func (*Route) Hosts

func (r *Route) Hosts() []string

Hosts returns the host patterns the route is restricted to, as written. It returns nil when the route answers on any host.

func (*Route) Meta

func (r *Route) Meta(key string) (any, bool)

Meta returns the annotation stored under key.

func (*Route) Method

func (r *Route) Method() string

Method returns the HTTP method the route answers.

func (*Route) Name

func (r *Route) Name() string

Name returns the route's name, or the empty string.

func (*Route) Params

func (r *Route) Params() []ParamInfo

Params returns the parameters the pattern declares, in order.

func (*Route) Pattern

func (r *Route) Pattern() string

Pattern returns the route template as written.

type RouteError

type RouteError struct {
	// Method is the HTTP method of the route that failed, if known.
	Method string
	// Pattern is the template of the route that failed.
	Pattern string
	// Err is the underlying cause.
	Err error
}

RouteError identifies which route a registration error came from, so that a gateway loading routes from user configuration can report the offending entry rather than just the failure.

func (*RouteError) Error

func (e *RouteError) Error() string

Error implements the error interface.

func (*RouteError) Unwrap

func (e *RouteError) Unwrap() error

Unwrap returns the underlying cause.

type RouteInfo

type RouteInfo struct {
	// Name is the route's name, or the empty string.
	Name string
	// Method is the HTTP method the route answers.
	Method string
	// PathTemplate is the pattern as written, for example "/users/{id}".
	PathTemplate string
	// Hosts are the host patterns the route is restricted to, as written. It is
	// nil when the route answers on any host.
	Hosts []string
	// Params describes the pattern's parameters in order.
	Params []ParamInfo
	// Handler is the handler the route was registered with, before middleware.
	Handler http.Handler
	// Meta carries the route's user annotations.
	Meta map[string]any
}

RouteInfo is a snapshot of a registered route, suitable for generating documentation such as an OpenAPI specification without reconstructing anything from regular expressions.

type RouteOption

type RouteOption func(*Route)

RouteOption customises a route at registration time.

func WithHost

func WithHost(patterns ...string) RouteOption

WithHost restricts a single route to the given host patterns, overriding whatever host constraint its group carried. See ParseHostPattern for the accepted forms.

func WithMeta

func WithMeta(key string, value any) RouteOption

WithMeta attaches an arbitrary annotation to the route. Annotations are reported by Routes and are how a documentation generator carries summaries, tags or schemas alongside a route.

func WithMiddleware

func WithMiddleware(mw ...Middleware) RouteOption

WithMiddleware returns a RouteOption that wraps only this route, inside any group middleware.

func WithName

func WithName(name string) RouteOption

WithName gives the route a name, which must be unique within the router.

type Router

type Router struct {
	// NotFound serves requests that matched no route. When nil,
	// http.NotFoundHandler is used.
	NotFound http.Handler

	// MethodNotAllowed serves requests whose path matched a route but whose
	// method did not. When nil, a handler writing 405 with an Allow header is
	// used.
	MethodNotAllowed http.Handler

	// CleanPath makes the router redirect a request whose path is not in
	// canonical form to the cleaned form, with 301.
	CleanPath bool

	// RedirectTrailingSlash makes the router redirect "/x/" to "/x", and
	// "/x" to "/x/", when only the other form is registered.
	RedirectTrailingSlash bool

	// RouteInContext makes the router attach the matched route to the request
	// even when the route declares no parameters, so that RouteOf works for
	// static routes too. It costs one allocation per request; leave it off if
	// handlers do not need it.
	RouteInContext bool
	// contains filtered or unexported fields
}

Router dispatches requests to registered handlers.

A router is safe for concurrent use once it is serving. Registering routes while requests are in flight is not: use Swap, which validates a new table off to the side and installs it atomically.

func New

func New() *Router

New returns an empty router.

func (*Router) DELETE

func (r *Router) DELETE(pattern string, h http.Handler, opts ...RouteOption) error

DELETE registers a handler for DELETE requests.

func (*Router) GET

func (r *Router) GET(pattern string, h http.Handler, opts ...RouteOption) error

GET registers a handler for GET requests.

func (*Router) Group

func (r *Router) Group(prefix string, mw ...Middleware) *Group

Group returns a group that prefixes its patterns and wraps its handlers.

func (*Router) HEAD

func (r *Router) HEAD(pattern string, h http.Handler, opts ...RouteOption) error

HEAD registers a handler for HEAD requests.

func (*Router) Handle

func (r *Router) Handle(method, pattern string, h http.Handler, opts ...RouteOption) error

Handle registers a handler for a method and pattern. It returns an error — never a panic — when the pattern is malformed, duplicates an existing route, or conflicts with one already registered.

func (*Router) HandleFunc

func (r *Router) HandleFunc(method, pattern string, h http.HandlerFunc, opts ...RouteOption) error

HandleFunc registers a handler function for a method and pattern.

func (*Router) Host

func (r *Router) Host(patterns ...string) *Group

Host returns a group whose routes only answer on the given host patterns. See ValidateHost for the accepted forms.

func (*Router) Lookup

func (r *Router) Lookup(req *http.Request) (*Route, bool)

Lookup returns the route that would serve req, without allocating and without capturing parameters.

func (*Router) LookupInto

func (r *Router) LookupInto(req *http.Request, params []PathParam) (*Route, []PathParam, bool)

LookupInto returns the route that would serve req and appends its captured parameters to params. Supplying a params slice with spare capacity makes the call allocation free.

func (*Router) OPTIONS

func (r *Router) OPTIONS(pattern string, h http.Handler, opts ...RouteOption) error

OPTIONS registers a handler for OPTIONS requests.

func (*Router) PATCH

func (r *Router) PATCH(pattern string, h http.Handler, opts ...RouteOption) error

PATCH registers a handler for PATCH requests.

func (*Router) POST

func (r *Router) POST(pattern string, h http.Handler, opts ...RouteOption) error

POST registers a handler for POST requests.

func (*Router) PUT

func (r *Router) PUT(pattern string, h http.Handler, opts ...RouteOption) error

PUT registers a handler for PUT requests.

func (*Router) Route

func (r *Router) Route(name string) *Route

Route returns the route registered under name, or nil.

func (*Router) Routes

func (r *Router) Routes() []RouteInfo

Routes returns a snapshot of every registered route, in registration order. It is everything a documentation generator needs: the template as written, the parameters it declares with their constraints and positions, the handler, and any annotations attached with WithMeta.

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements http.Handler.

func (*Router) String

func (r *Router) String() string

String renders the route table, which is useful in tests and in start-up logs.

func (*Router) Swap

func (r *Router) Swap(build func(*Builder) error) error

Swap replaces the route table. build is called with a fresh, empty builder; if it returns an error, or if any registration inside it fails, the router's existing table is left untouched. Otherwise the new table is installed atomically and requests already in flight finish against the old one.

This is the reload path: a route table assembled from user-supplied configuration can be rejected in full without taking the process down.

A Group obtained from the router before a swap belongs to the replaced builder and registering on it afterwards has no effect on the live table. Build every group from the Builder the callback is given.

func (*Router) Use

func (r *Router) Use(mw ...Middleware)

Use appends router-level middleware. It applies to every route, including routes registered before the call, outermost first in registration order.

Directories

Path Synopsis
internal
template
Package template parses route templates of the form "/users/{id}" and "/users/{id:[0-9]+}" into a compiled regular expression, an ordered list of variable names, and a reverse-building template used for URL construction.
Package template parses route templates of the form "/users/{id}" and "/users/{id:[0-9]+}" into a compiled regular expression, an ordered list of variable names, and a reverse-building template used for URL construction.
tree
Package tree implements the segment-indexed prefix tree used to match routes whose templates consist of static segments, whole-segment wildcards with an optional type constraint, and an optional trailing catch-all.
Package tree implements the segment-indexed prefix tree used to match routes whose templates consist of static segments, whole-segment wildcards with an optional type constraint, and an optional trailing catch-all.
Package muxcompat is a drop-in replacement for github.com/gorilla/mux.
Package muxcompat is a drop-in replacement for github.com/gorilla/mux.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL