cors-middleware.mjs
65 lines 2.3 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 1 day ago
1 /**
2 * CORS for hosted gateway: browsers reject Access-Control-Allow-Origin: * together with
3 * Access-Control-Allow-Credentials: true, which surfaces as fetch() "Failed to fetch".
4 * When HUB_CORS_ORIGIN is unset, use * and omit credentials. When set, echo allowed origin + credentials.
5 *
6 * If the allowlist has only one of `https://example.com` and `https://www.example.com`, a request
7 * from the other still matches: we echo the **request** Origin so credentialed fetches from apex
8 * vs www both succeed (operators often list only one host; mismatch previously blanked Hub Settings).
9 */
10
11 /**
12 * Same scheme + hostname differs only by leading `www.` (e.g. apex vs www for one site).
13 * @param {string} a
14 * @param {string} b
15 */
16 export function isWwwApexPair(a, b) {
17 if (a === b) return true;
18 try {
19 const ua = new URL(a);
20 const ub = new URL(b);
21 if (ua.protocol !== ub.protocol) return false;
22 const A = ua.hostname;
23 const B = ub.hostname;
24 return A === B || A === `www.${B}` || B === `www.${A}`;
25 } catch {
26 return false;
27 }
28 }
29
30 /**
31 * @param {string | undefined} requestOrigin
32 * @param {string[]} corsOrigins
33 * @returns {string}
34 */
35 export function resolveGatewayAllowOrigin(requestOrigin, corsOrigins) {
36 if (corsOrigins.length === 0) return '*';
37 if (requestOrigin && corsOrigins.includes(requestOrigin)) return requestOrigin;
38 if (requestOrigin) {
39 for (const o of corsOrigins) {
40 if (isWwwApexPair(o, requestOrigin)) return requestOrigin;
41 }
42 }
43 return corsOrigins[0];
44 }
45
46 /**
47 * @param {import('express').Response} res
48 * @param {string | undefined} requestOrigin - req.get('Origin')
49 * @param {string[]} corsOrigins - trimmed list from HUB_CORS_ORIGIN
50 */
51 export function applyGatewayCors(res, requestOrigin, corsOrigins) {
52 let allow;
53 if (corsOrigins.length > 0) {
54 allow = resolveGatewayAllowOrigin(requestOrigin, corsOrigins);
55 } else {
56 allow = '*';
57 }
58 res.set('Access-Control-Allow-Origin', allow);
59 res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
60 res.set('Access-Control-Allow-Headers', 'Authorization, Content-Type, X-Vault-Id, X-User-Id');
61 if (corsOrigins.length > 0 && allow !== '*') {
62 res.set('Access-Control-Allow-Credentials', 'true');
63 }
64 if (corsOrigins.length > 0) res.set('Vary', 'Origin');
65 }
File History 2 commits
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 1 day ago
sha256:9103f98c89257ed2b01c237cea895dabb3e85ea337dccb1161c175e4422355b6 docs: accept Calendar Events v0 spec with Phase 0 security … Human 1 day ago