cors-middleware.mjs
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