UNPKG

4.32 kBJavaScriptView Raw
1export const ORIGIN = 'Origin';
2export const REQUEST_METHOD = 'Access-Control-Request-Method';
3export const REQUEST_HEADERS = 'Access-Control-Request-Headers';
4export const ALLOW_ORIGIN = 'Access-Control-Allow-Origin';
5export const ALLOW_METHODS = 'Access-Control-Allow-Methods';
6export const ALLOW_HEADERS = 'Access-Control-Allow-Headers';
7export const ALLOW_CREDENTIALS = 'Access-Control-Allow-Credentials';
8export const VARY = 'VARY';
9const SECOND = { unit: 'second', relativeTo: '1970-01-01' };
10const isDuration = (x) => (x === null || x === void 0 ? void 0 : x[Symbol.toStringTag]) === 'Temporal.Duration';
11const toMaxAge = (x) => (isDuration(x) ? x.total(SECOND) : x).toString();
12/**
13 * A CORS middleware that gives clients exactly the permissions they ask for, unless constrained by the definitions in `options`.
14 *
15 * Note that applying this middleware to your routes isn't enough for non-GET requests.
16 * Pre-flight/OPTIONS routes need to be added manually:
17 * ```
18 * router.options('/your/path', anyCORS(), () => noContent())
19 * router.post('/your/path', anyCORS(), (req, {}) => ok())
20 * ```
21 */
22export const cors = (options = {}) => async (ax) => {
23 const x = await ax;
24 const req = x.request;
25 x.effects.push(res => {
26 var _a, _b, _c, _d, _e, _f, _g, _h;
27 const optOrigin = typeof options.origin === 'string'
28 ? new URL(options.origin)
29 : options.origin;
30 res.headers.set(ALLOW_ORIGIN, (_b = (_a = optOrigin === null || optOrigin === void 0 ? void 0 : optOrigin.origin) !== null && _a !== void 0 ? _a : req.headers.get(ORIGIN)) !== null && _b !== void 0 ? _b : '*');
31 const requestedMethod = req.headers.get(REQUEST_METHOD);
32 if (requestedMethod && ((_d = (_c = options.methods) === null || _c === void 0 ? void 0 : _c.includes(requestedMethod)) !== null && _d !== void 0 ? _d : true)) {
33 res.headers.append(ALLOW_METHODS, requestedMethod);
34 }
35 const requestedHeaders = new Set((_f = (_e = req.headers.get(REQUEST_HEADERS)) === null || _e === void 0 ? void 0 : _e.split(',')) === null || _f === void 0 ? void 0 : _f.map(h => h.trim()));
36 for (const h of (_h = (_g = options.headers) === null || _g === void 0 ? void 0 : _g.filter(h => requestedHeaders.has(h))) !== null && _h !== void 0 ? _h : requestedHeaders) {
37 res.headers.append(ALLOW_HEADERS, h);
38 }
39 if (options.credentials)
40 res.headers.set(ALLOW_CREDENTIALS, 'true');
41 if (options.maxAge)
42 res.headers.set('Access-Control-Max-Age', toMaxAge(options.maxAge));
43 if (!options.origin)
44 res.headers.append(VARY, ORIGIN);
45 if (!options.methods)
46 res.headers.append(VARY, REQUEST_METHOD);
47 if (!options.headers)
48 res.headers.append(VARY, REQUEST_HEADERS);
49 return res;
50 });
51 return x;
52};
53export { cors as anyCORS };
54/**
55 * A CORS middleware that only grants the permissions defined via `options`.
56 *
57 * Note that applying this middleware to your routes isn't enough for non-GET requests.
58 * Pre-flight/OPTIONS routes need to be added manually:
59 * ```
60 * router.options('/your/path', strictCORS({ ... }), () => noContent())
61 * router.post('/your/path', strictCORS({ ... }), (req, {}) => ok())
62 * ```
63 */
64export const strictCORS = (options) => async (ax) => {
65 const x = await ax;
66 const req = x.request;
67 x.effects.push(res => {
68 const optOrigin = typeof options.origin === 'string'
69 ? new URL(options.origin)
70 : options.origin;
71 res.headers.set(ALLOW_ORIGIN, optOrigin.origin);
72 const requestedMethod = req.headers.get(REQUEST_METHOD);
73 if (requestedMethod && options.methods.includes(requestedMethod)) {
74 for (const m of options.methods) {
75 res.headers.append(ALLOW_METHODS, m);
76 }
77 }
78 if (req.headers.get(REQUEST_HEADERS)) {
79 for (const h of options.headers) {
80 res.headers.append(ALLOW_HEADERS, h);
81 }
82 }
83 if (options.credentials)
84 res.headers.set(ALLOW_CREDENTIALS, 'true');
85 if (options.maxAge)
86 res.headers.set('Access-Control-Max-Age', toMaxAge(options.maxAge));
87 return res;
88 });
89 return x;
90};
91//# sourceMappingURL=cors.js.map
\No newline at end of file