Routing Basics
CORS - itty-router breaking changes in v5
v5.x includes an all-new CORS solution replacing the previous createCors
. v5 cors
is very similar (it still creates a preflight
and corsify
pair), but the options have all been replaced with industry standard ones, such as those used in express.js.
cors(CorsOptions?) => { preflight, corsify }
Example
import { AutoRouter, cors } from 'itty-router'
// get preflight and corsify pair
const { preflight, corsify } = cors()
const router = AutoRouter({
before: [preflight], // add preflight upstream
finally: [corsify], // and corsify downstream
})
router.get('/', () => 'Hello World!')
export default router
How It Works
The cors
function returns an upstream middleware (preflight
) and downstream response handler (corsify
).
const { preflight, corsify } = cors()
preflight middleware
(request: IRequest): Response | void
Responds to OPTIONS
requests. Include this as upstream middleware.
import { Router, cors } from 'itty-router'
const { preflight, corsify } = cors()
const router = Router({
before: [preflight], // <-- add to "before" stage
})
import { Router, cors } from 'itty-router'
const { preflight, corsify } = cors()
const router = Router()
router
.options('*', preflight) // <-- add to "options" or "all" channel
corsify response handler changed in v5
(response: Response, request?: IRequest): Response
Adds the CORS headers to existing Responses
(e.g. as created by json
or text
). Include this at the very end of your response chain, as it should occur after any errors are caught.
The new corsify
function now optionally accepts a `Request` as a second argument, allowing origin-reflection when required. In order to use { credentials: true, origin: '*' }
, the `Request` argument will be required.
import { AutoRouter, cors } from 'itty-router'
const { preflight, corsify } = cors()
const router = AutoRouter({
before: [preflight],
finally: [corsify],
})
export default router
import { Router, cors, error, json } from 'itty-router'
const { preflight, corsify } = cors()
const router = Router({
before: [preflight],
catch: error,
finally: [json, corsify],
})
export default router
import { Router, cors, json, error } from 'itty-router'
const { preflight, corsify } = cors()
const router = Router()
router
.options('*', preflight) // .all() channel also works
export default {
fetch: (request, ...args) =>
router
.fetch(request, ...args)
.then(json)
.catch(error)
.then((r) => corsify(r, request)) // <-- add corsify at the end
}
CorsOptions new in v5
Name (Default Value) | Description | Supported Format | Example |
---|---|---|---|
origin ("*" ) | Controls Access-Control-Allow-Origin header. Defaults to wildcard. | string | "https://foo.bar" |
If a match is found, request origin is reflected. | string[] | ["https://foo.bar", "http://cat.dog"] | |
If set to true , request origin is reflected. | true | true | |
If RegExp matches origin, request origin is reflected. | RegExp | /\.example.com$/ | |
Sets allowed origin to whatever the function returns. | (origin: string) => string | void | (o) => o.endsWith('.com') ? o : undefined | |
credentials (undefined ) | Set to true to allow credentials to be sent (Access-Control-Allow-Credentials ) | true | true |
allowMethods ("*" ) | Controls Access-Control-Allow-Methods header. Defaults to wildcard (all methods supported). | string | "GET, POST" |
Array format will be joined automatically. | string[] | ["GET, "POST"] | |
allowHeaders (undefined ) | Controls Access-Control-Allow-Headers header, allowing custom headers to be sent by the request. | string | "x-foo,x-bar" |
Array format will be joined automatically. | string[] | ["x-foo, "x-bar"] | |
exposeHeaders (undefined ) | Controls Access-Control-Expose-Headers header, allowing custom headers to be read. | string | "x-foo,x-bar" |
Array format will be joined automatically. | string[] | ["x-foo, "x-bar"] | |
maxAge (undefined ) | Controls Access-Control-Max-Age header, controlling how long (in seconds) preflight responses are cached in the browser. | number | 84600 |
Example (Options)
import { Router, cors } from 'itty-router'
const { preflight, corsify } = cors({
origin: '*',
origin: true,
origin: 'https://foo.bar',
origin: ['https://foo.bar', 'https://dog.cat'],
origin: /oo.bar$/,
origin: (origin) => origin.endsWith('foo.bar') ? origin : undefined,
credentials: true,
allowMethods: '*',
allowMethods: 'GET, POST',
allowMethods: ['GET', 'POST'],
allowHeaders: 'x-foo, x-bar',
allowHeaders: ['x-foo', 'x-bar'],
exposeHeaders: 'x-foo, x-bar',
exposeHeaders: ['x-foo', 'x-bar'],
maxAge: 84600,
})
const router = Router({
before: [preflight],
finally: [corsify],
})