Skip to content

Options

ShiftAPI uses a layered option system. Options configure the API, groups, and individual routes.

TypeWhere it worksExamples
OptionAPI, Group, and RouteWithError, WithMiddleware, WithResponseHeader
APIOptionAPI only (New)WithInfo, WithBadRequestError, WithInternalServerError
RouteOptionRoute only (Handle)WithStatus, WithRouteInfo

Option implements all three level interfaces, so WithError and WithMiddleware work everywhere. Level-specific options like WithStatus are restricted to their level at compile time.

Use ComposeOptions to bundle multiple Option values into a single reusable option that works at any level:

func WithAuth() shiftapi.Option {
return shiftapi.ComposeOptions(
shiftapi.WithMiddleware(authMiddleware),
shiftapi.WithError[*AuthError](http.StatusUnauthorized),
)
}
// Works at any level
api := shiftapi.New(WithAuth())
v1 := api.Group("/api/v1", WithAuth())
shiftapi.Handle(v1, "GET /secret", getSecret, WithAuth())

To mix shared options with level-specific options, use the corresponding compose function:

FunctionAcceptsReturns
ComposeOptions...OptionOption
ComposeAPIOptions...APIOptionAPIOption
ComposeGroupOptions...GroupOptionGroupOption
ComposeRouteOptions...RouteOptionRouteOption

Since Option implements all level interfaces, you can pass it to any of the level-specific compose functions alongside level-specific options:

createOpts := shiftapi.ComposeRouteOptions(
shiftapi.WithStatus(http.StatusCreated), // RouteOption
shiftapi.WithError[*ConflictError](http.StatusConflict), // Option (also a RouteOption)
)
shiftapi.Handle(api, "POST /users", createUser, createOpts)

Use Group to register routes under a common path prefix with shared options:

v1 := api.Group("/api/v1",
shiftapi.WithError[*RateLimitError](http.StatusTooManyRequests),
shiftapi.WithMiddleware(auth),
)
shiftapi.Handle(v1, "GET /users", listUsers) // GET /api/v1/users
shiftapi.Handle(v1, "POST /users", createUser) // POST /api/v1/users

Groups can be nested. Error types and middleware are inherited by child groups:

admin := v1.Group("/admin",
shiftapi.WithError[*ForbiddenError](http.StatusForbidden),
shiftapi.WithMiddleware(adminOnly),
)
shiftapi.Handle(admin, "GET /stats", getStats) // GET /api/v1/admin/stats
// inherits RateLimitError (429) + auth middleware from v1
// adds ForbiddenError (403) + adminOnly middleware

Options merge across all three levels: New() (API-wide) → Group() (group-level) → route registration (route-level).