Routes
A route maps an incoming request to an upstream. The routes field is an array; it defaults to
empty. Each route must reference an upstream that exists in upstreams
(validation fails otherwise), and its path must start with /.
routes:
- path: /api/users
methods: [GET, POST]
upstream: user-service
priority: 10
strip_prefix: /api
timeout: 15s
auth_provider: primary-jwt
require_roles: [admin]
rate_limit:
requests_per_window: 100
window_size: 1m
cors:
allowed_origins: ["https://app.example.com"]
allow_credentials: trueroutes[]01
| Key | Type | Default | Description |
path | string | — | Path pattern to match. Required (must start with /). |
methods | array of string | [] | HTTP methods to match. Empty means all methods. |
upstream | string | — | Target upstream name. Required (must exist in upstreams). |
priority | integer | 0 | Higher priority routes are matched first. |
strip_prefix | string | none | Prefix removed from the path before proxying. |
add_prefix | string | none | Prefix prepended to the path before proxying. |
metadata | map of string→string | {} | Arbitrary route metadata. |
auth_provider | string | none | Auth provider name for this route (overrides the global auth.default_provider). |
skip_auth | boolean | false | Skip authentication for this route. |
require_roles | array of string | [] | Roles required for authorization. |
require_scopes | array of string | [] | Scopes required for authorization. |
authz_rule | string | none | Custom authorization rule (a Rhai expression). |
timeout | duration | none | Per-route request timeout, overriding gateway.request_timeout. |
rate_limit | object | none | Per-route rate limit. See below. |
cors | object | none | Per-route CORS override. See below. |
Routes have no retry or canary fields. Authentication and authorization behavior set here is
evaluated by the auth middleware — see Authentication & authorization
and the Security section for the request flow.
Rate limit02
Per-route rate_limit and cors are enforced. rate_limit applies a fixed window per route
(keyed by the route's path), returning 429 with Retry-After when exceeded — note it currently
uses an in-process counter (per replica; a shared backend for cross-replica limits is planned).
cors applies the matched route's override when a top-level cors
block is set (which adds the CORS middleware to the chain). See Middleware.
The per-route rate_limit object uses a fixed window: a number of requests allowed per window
duration.
rate_limit:
requests_per_window: 100
window_size: 1m| Key | Type | Default | Description |
requests_per_window | integer | — | Requests allowed per window. Required. |
window_size | duration | — | Window length. Required. |
This is the real schema. Older example files use rate_limit: { requests_per_second: ... },
which is not a valid field and is silently ignored.
CORS03
The per-route cors object overrides the global cors policy for this
route.
cors:
allowed_origins: ["https://app.example.com"]
allowed_methods: [GET, POST]
allowed_headers: [Authorization, Content-Type]
allow_credentials: true
max_age: 3600| Key | Type | Default | Description |
allowed_origins | array of string | [] | Permitted origins. |
allowed_methods | array of string | [] | Permitted HTTP methods. |
allowed_headers | array of string | [] | Permitted request headers. |
allow_credentials | boolean | false | Allow credentials (cookies, auth headers). |
max_age | integer (seconds) | 3600 | Preflight cache max age. |
See Routing for how path matching and priority resolve to a single route.