Documentation
¶
Overview ¶
Package fibermid provides middleware and helper functions for the Fiber web framework. It supports header-based API version routing, response helpers, and a generic registration entry point that wires repositories → controllers → handlers and registers them under a version prefix.
This package consolidates the versioning runtime, request-scoped context keys, and HTTP error taxonomy that fibermid relies on into a single dependency-light module.
Index ¶
- Constants
- Variables
- func AppendToHandlers(apiHandlers map[string]map[string]fiber.Handler, ...)
- func ExtractVersion(header string) string
- func GetErrorCode(err error) int
- func HandleResponse(c *fiber.Ctx, obj any, err error) error
- func Init[T any](app *fiber.App, ctx context.Context, cfg T, log *zerolog.Logger)
- func MountVersionedRoutes(app *fiber.App, apiHandlers map[string]map[string]fiber.Handler, ...)
- func RegisterAPIVersion[TRepo any, TController any, THandler any](app *fiber.App, repo TRepo, version string, ...)
- func SetAnyResponse[T any](c *fiber.Ctx, err T, status int) error
- func SetResponse(c *fiber.Ctx, body any, status int) error
- func VersionPathMiddleware(defaultVersion string, skipPaths ...string) fiber.Handlerdeprecated
- func VersionRouter(c *fiber.Ctx, apiHandlers map[string]map[string]fiber.Handler) errordeprecated
- type Error
- type InternalServer
- type InvalidInput
- type NotFound
- type Response
- type TransientError
- type Unauthorized
Constants ¶
const LatestVersion = "latest"
Variables ¶
var ( CfgCtxKey contextKey = "config" LogHelpCtxKey contextKey = "loghelp" )
Functions ¶
func AppendToHandlers ¶
func AppendToHandlers(apiHandlers map[string]map[string]fiber.Handler, m map[string]map[string]fiber.Handler)
AppendToHandlers merges the per-route inner maps from m into apiHandlers. Existing entries for the same path are preserved (per-method inner keys are merged, not overwritten) so v1 and v2 can coexist on the same shared map.
func ExtractVersion ¶
ExtractVersion parses an Accept-style header to extract a `version=` parameter. When present, the version is returned with a leading "v" (e.g., "v1"). When absent it returns "".
func GetErrorCode ¶
GetErrorCode maps an error to its HTTP status code based on the typed errors above; unknown errors default to 500.
func HandleResponse ¶
HandleResponse writes a Response envelope. On error, the HTTP status code is derived from the error type via GetErrorCode.
func Init ¶
Init wires per-request logging and stashes the config + a request-scoped logger into the Fiber context. The generic type parameter lets callers pass any config struct without this package depending on it.
func MountVersionedRoutes ¶
func MountVersionedRoutes(app *fiber.App, apiHandlers map[string]map[string]fiber.Handler, defaultVersion string)
MountVersionedRoutes binds Fiber routes at the BARE paths derived from `apiHandlers` (which is populated by oapi-codegen-emitted `RegisterHandlerVersionsWithOptions` calls). External clients see only bare paths (e.g. `/events`, `/events/:id`); the registered Fiber handler is a dispatcher that picks the per-version handler from `apiHandlers` based on the `API-Version` (or `X-API-Version`) request header. When the header is absent, defaultVersion is used.
`apiHandlers` is the standard map shape produced by the fork's Fiber templates:
"/v1/events/:id" -> { "GET": wrapper.GetEvent, "PUT": wrapper.UpdateEvent }
"/v2/events/:id" -> { "GET": wrapper.GetEvent, "PUT": wrapper.UpdateEvent }
"/latest/events/:id" -> ... (set by the templates as an alias)
Path parameters are handled correctly here because the bare-path Fiber route does the matching: the dispatcher receives a `*fiber.Ctx` whose `c.Params(...)` is already populated, and it forwards that same ctx to the per-version wrapper. The wrapper's `c.Params("id")` reads the value the bare-path route extracted.
Typical usage in a service's server.go:
apiHandlers := make(map[string]map[string]fiber.Handler)
v1.RegisterHandlerVersionsWithOptions(app, v1Handler, "v1", apiHandlers, v1.FiberServerOptions{})
v2.RegisterHandlerVersionsWithOptions(app, v2Handler, "v2", apiHandlers, v2.FiberServerOptions{})
fibermid.MountVersionedRoutes(app, apiHandlers, "v1")
This binds `/events`, `/events/:id`, `/versions` etc. as the only externally visible URLs. `/v1/...` and `/v2/...` are NOT registered as Fiber routes; a request to those will 404.
func RegisterAPIVersion ¶
func RegisterAPIVersion[TRepo any, TController any, THandler any]( app *fiber.App, repo TRepo, version string, newController func(TRepo) TController, newHandler func(TController) THandler, registerHandlers func(*fiber.App, THandler, string) map[string]map[string]fiber.Handler, apiHandlers map[string]map[string]fiber.Handler, )
RegisterAPIVersion wires a repo → controller → handler chain for one API version, registers the handler routes via the caller-supplied registerHandlers function (typically generated by oapi-codegen), and merges the resulting route map into the shared apiHandlers table that VersionRouter dispatches against.
func SetAnyResponse ¶
SetAnyResponse marshals the typed err value and writes it with the given status code. Useful when the caller wants the wire shape to match a typed generated error rather than fibermid's default Error envelope.
func SetResponse ¶
SetResponse marshals body as JSON and writes it with the given status code.
func VersionPathMiddleware
deprecated
VersionPathMiddleware returns a Fiber middleware that resolves the effective API version from the `API-Version` (or `X-API-Version`) header and rewrites the request path to add a `/<version>` prefix when the request didn't already carry one. After rewriting, it calls c.RestartRouting() so Fiber's normal route tree (with proper path-param support) dispatches the request to the version-prefixed handler.
Deprecated: this exposes `/v<n>/...` URLs publicly via the registered per-version routes. Prefer MountVersionedRoutes (header-only, bare-path-only) for new services that want to keep the URL space version-free.
Behavior:
- When the request path already starts with `/v<digits>/` (or equals `/v<digits>`), the middleware passes through unchanged.
- Paths whose exact value is in skipPaths (e.g. `/healthchecks`) pass through unchanged.
- Otherwise, the middleware reads the version from `API-Version` (or `X-API-Version`), falling back to defaultVersion if neither is set, prepends `/<version>` to the path, and restarts routing.
func VersionRouter
deprecated
VersionRouter dispatches the request to the handler registered under the versioned key matching the incoming `API-Version` header (or the deprecated `X-API-Version` / Accept-version fallbacks).
Deprecated: this dispatcher uses literal map-key lookup, so the keys produced by the registerHandlers callback must contain the literal request path — path-parameter routes (e.g. "/v1/events/:id") are NOT pattern-matched here, and a request like `GET /events/1` with `API-Version: v1` will fall through to "versioned route not found". Use VersionPathMiddleware instead.
Types ¶
type InternalServer ¶
type InternalServer struct {
Err error
}
InternalServer is an error type for internal server errors (500).
func (InternalServer) Error ¶
func (t InternalServer) Error() string
type InvalidInput ¶
type InvalidInput struct {
Err error
}
InvalidInput is an error type for invalid input (400).
func (InvalidInput) Error ¶
func (t InvalidInput) Error() string
type TransientError ¶
type TransientError struct {
Err error
}
TransientError is an error type for transient errors (503).
func (TransientError) Error ¶
func (t TransientError) Error() string
type Unauthorized ¶
type Unauthorized struct {
}
Unauthorized is an error type for authorization errors (401).
func (Unauthorized) Error ¶
func (t Unauthorized) Error() string