CORS
ingenium.cors is the built-in CORS middleware. It handles simple requests, preflight OPTIONS, and sets Vary: Origin whenever the origin is reflected from the request.
Usage
app.use(ingenium.cors({
origin: 'https://app.example.com', // or true | string[] | RegExp | (origin, ctx) => boolean | string | Promise<>
methods: ['GET', 'POST', 'PUT'], // default: GET HEAD PUT PATCH POST DELETE
allowedHeaders: ['x-trace-id'], // default: mirror Access-Control-Request-Headers
exposedHeaders: ['x-trace-id'],
credentials: true, // throws at construction with origin: '*'
maxAge: 3600, // preflight cache seconds
optionsSuccessStatus: 204,
}))
Behavior
- Simple requests - the
Access-Control-Allow-Originheader is written based on the resolvedoriginoption, plusVary: Originwhen the origin is reflected from the request. - Preflights -
OPTIONSrequests withAccess-Control-Request-Methodget a 204 with the negotiated methods/headers and do not callnext(). - Credentials - setting
credentials: truetogether withorigin: '*'throws at construction. A wildcard origin with credentials is forbidden by the spec; the middleware fails loud instead of producing a misconfigured response at runtime.
Origin shapes
The origin option accepts:
true- reflect the request'sOriginheader.string- exact match.string[]- match against a list of exact origins.RegExp- match against a regular expression.(origin, ctx) => boolean | string | Promise<boolean | string>- full custom predicate, optionally async, optionally returning a different origin string to send back.
Where to next?
- Middleware - the dispatch model.
- CSRF - cookie protection for state-changing requests.
- Production hardening - the full prod wiring.
- Trust proxy - getting
ctx.hostnameright behind a proxy.