Documentation
¶
Overview ¶
Package router makes routes DATA.
The usual way of registering routes — calling r.Get(...) in a Register function — throws away everything about them the moment it runs. Nothing can tell you afterwards which routes exist, which are unguarded, or what they do, because the registration was a side effect rather than a value.
So a controller here RETURNS its routes instead of registering them. The same value that mounts the route also answers `icpt routes`, generates the OpenAPI document, and lets a structural test assert that every mutating route in the tree carries an authentication guard. That last one is the reason this design is worth the small ceremony: a missing guard becomes a failing test rather than an incident.
func (c *ProductController) Routes() []router.Route {
return []router.Route{
router.Get("/", c.List).Summary("List products").Tag("catalog"),
router.Post("/", c.Create).Guard(guard.Tenanted).Summary("Create a product"),
router.Get("/:id", c.Get).Param("id", "Product id"),
}
}
Index ¶
- func Mount(r fiber.Router, routes []Route, opt MountOptions) error
- func MountController(r fiber.Router, c Controller, opt MountOptions) error
- type Controller
- type ControllerFunc
- type Doc
- type MountOptions
- type Mounted
- type ParamDoc
- type Registry
- type Route
- func Delete(path string, h fiber.Handler) Route
- func Get(path string, h fiber.Handler) Route
- func Head(path string, h fiber.Handler) Route
- func New(method, path string, h fiber.Handler) Route
- func Options(path string, h fiber.Handler) Route
- func Patch(path string, h fiber.Handler) Route
- func Post(path string, h fiber.Handler) Route
- func Put(path string, h fiber.Handler) Route
- func (r Route) Accepts(sample any) Route
- func (r Route) AsPublic() Route
- func (r Route) Deprecate() Route
- func (r Route) Describe(s string) Route
- func (r Route) Guard(g ...guard.Guard) Route
- func (r Route) HeaderParam(name, description string) Route
- func (r Route) ID(id string) Route
- func (r Route) Intercept(i ...interceptor.Interceptor) Route
- func (r Route) Param(name, description string) Route
- func (r Route) QueryParam(name, description string) Route
- func (r Route) Returns(sample any, statuses ...int) Route
- func (r Route) Summary(s string) Route
- func (r Route) Tag(t ...string) Route
- func (r Route) Use(h ...fiber.Handler) Route
- type RouteJSON
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Mount ¶
func Mount(r fiber.Router, routes []Route, opt MountOptions) error
Mount registers routes on a Fiber router and records them.
Per-route guards are attached as handlers on that route alone, rather than with r.Use: a Use on a group applies to every route after it, which means adding a public route below a protected one silently exposes it. Attaching per route makes each line say exactly what protects it.
func MountController ¶
func MountController(r fiber.Router, c Controller, opt MountOptions) error
MountController mounts everything a controller declares.
Types ¶
type Controller ¶
type Controller interface {
Routes() []Route
}
Controller exposes a set of routes. A controller holds no state beyond its service dependency and contains no business logic: it reads the request, calls a service, renders the result.
type ControllerFunc ¶
type ControllerFunc func() []Route
ControllerFunc adapts a plain function to Controller.
func (ControllerFunc) Routes ¶
func (f ControllerFunc) Routes() []Route
Routes implements Controller.
type Doc ¶
type Doc struct {
OperationID string `json:"operationId,omitempty"`
Summary string `json:"summary,omitempty"`
Description string `json:"description,omitempty"`
Tags []string `json:"tags,omitempty"`
Params []ParamDoc `json:"params,omitempty"`
// RequestBody and Response are sample values (usually a zero DTO) that
// the OpenAPI generator reflects over.
RequestBody any `json:"-"`
Response any `json:"-"`
// Statuses the route can return beyond the success one.
Statuses []int `json:"statuses,omitempty"`
Deprecated bool `json:"deprecated,omitempty"`
}
Doc is everything about a route that is for humans and generators rather than for the router: the OpenAPI surface.
It is a nested struct rather than fields on Route so that the fluent builders below can carry the obvious names — Summary, Tags, Response — and still be methods.
type MountOptions ¶
type MountOptions struct {
// Module names the owner in the registry, e.g. "catalog.products".
Module string
// Prefix is the path already applied to r by the caller's Group calls.
// Mount cannot read it back off a fiber.Router, so pass it here or the
// recorded FullPath will be wrong.
Prefix string
// Registry records the mounted routes. Optional.
Registry *Registry
// Guards apply to every route mounted in this call, before the route's
// own. A module-wide authentication guard belongs here.
Guards []guard.Guard
// Interceptors apply to every route, outside the route's own.
Interceptors []interceptor.Interceptor
}
MountOptions configures Mount.
type Mounted ¶
type Mounted struct {
Route
// FullPath includes every group prefix — this is what a client calls.
FullPath string
// Module is the dotted owner, "catalog.products".
Module string
// GuardNames is flattened for printing and for assertions.
GuardNames []string
}
Mounted is a route after mounting: the declared metadata plus the full path it actually answers on.
type ParamDoc ¶
type ParamDoc struct {
Name string `json:"name"`
In string `json:"in"` // path | query | header
Description string `json:"description,omitempty"`
Required bool `json:"required,omitempty"`
Example string `json:"example,omitempty"`
}
ParamDoc documents a path, query or header parameter for the generated OpenAPI document.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry records every mounted route.
It is what makes the route table introspectable: `icpt routes` prints it, the OpenAPI generator walks it, and a structural test asserts over it. The zero value is ready to use.
func (*Registry) All ¶
All returns every mounted route, sorted by path then method, so the output is stable across runs — a route table that reorders itself cannot be diffed, and a diffable route table catches an accidental route change in code review.
func (*Registry) Unguarded ¶
Unguarded returns every mutating route (POST, PUT, PATCH, DELETE) that carries neither a guard nor an explicit Public marker.
Assert that this is empty in a test. It is the cheapest security control in the framework: the failure it catches — a new write endpoint shipped without authentication — is both common and expensive.
type Route ¶
type Route struct {
Method string
Path string
Handler fiber.Handler
// Guards run before the handler, in order.
Guards []guard.Guard
// Interceptors wrap the handler; the first is outermost.
Interceptors []interceptor.Interceptor
// Middleware is an escape hatch for Fiber handlers that are neither a
// guard nor an interceptor — a body limit, a websocket upgrade.
Middleware []fiber.Handler
// Doc carries the documentation surface.
Doc Doc
// Public marks a route as deliberately unauthenticated. Structural tests
// use it to tell "no guard because it is public" apart from "no guard
// because somebody forgot", which otherwise look identical.
Public bool
}
Route is one HTTP endpoint, with everything known about it in one value.
func (Route) HeaderParam ¶
HeaderParam documents a request header.
func (Route) Intercept ¶
func (r Route) Intercept(i ...interceptor.Interceptor) Route
Intercept appends interceptors; the first added is the outermost.
func (Route) QueryParam ¶
QueryParam documents an optional query parameter.
type RouteJSON ¶ added in v1.1.0
type RouteJSON struct {
Method string `json:"method"`
Path string `json:"path"`
FullPath string `json:"full_path"`
Module string `json:"module"`
GuardNames []string `json:"guards"`
Public bool `json:"public"`
}
RouteJSON is the data-only representation used by route dumps.
func JSONRoutes ¶ added in v1.1.0
JSONRoutes converts mounted routes into a serializable data-only view.