UNPKG

@elysiajs/cors

Version:

Plugin for Elysia that for Cross Origin Requests (CORs)

136 lines (135 loc) 4.72 kB
// src/index.ts import { Elysia } from "elysia"; var isBun = typeof new Headers()?.toJSON === "function"; var processHeaders = (headers) => { if (isBun) return Object.keys(headers.toJSON()).join(", "); let keys = ""; let i = 0; headers.forEach((_, key) => { if (i) keys = keys + ", " + key; else keys = key; i++; }); return keys; }; var cors = (config) => { let { aot = true, origin = true, methods = true, allowedHeaders = true, exposeHeaders = true, credentials = true, maxAge = 5, preflight = true } = config ?? {}; if (Array.isArray(allowedHeaders)) allowedHeaders = allowedHeaders.join(", "); if (Array.isArray(exposeHeaders)) exposeHeaders = exposeHeaders.join(", "); const origins = typeof origin === "boolean" ? void 0 : Array.isArray(origin) ? origin : [origin]; const app = new Elysia({ name: "@elysiajs/cors", seed: config, aot }); const anyOrigin = origins?.some((o) => o === "*"); const originMap = {}; if (origins) { for (const origin2 of origins) if (typeof origin2 === "string") originMap[origin2] = true; } const processOrigin = (origin2, request, from) => { if (Array.isArray(origin2)) return origin2.some((o) => processOrigin(o, request, from)); switch (typeof origin2) { case "string": if (from in originMap) return true; const fromProtocol = from.indexOf("://"); if (fromProtocol !== -1) from = from.slice(fromProtocol + 3); return origin2 === from; case "function": return origin2(request) === true; case "object": if (origin2 instanceof RegExp) return origin2.test(from); } return false; }; const handleOrigin = (set, request) => { if (origin === true) { set.headers.vary = "*"; set.headers["access-control-allow-origin"] = request.headers.get("Origin") || "*"; return; } if (anyOrigin) { set.headers.vary = "*"; set.headers["access-control-allow-origin"] = "*"; return; } if (!origins?.length) return; const headers = []; if (origins.length) { const from = request.headers.get("Origin") ?? ""; for (let i = 0; i < origins.length; i++) { const value = processOrigin(origins[i], request, from); if (value === true) { set.headers.vary = origin ? "Origin" : "*"; set.headers["access-control-allow-origin"] = from || "*"; return; } } } set.headers.vary = "Origin"; if (headers.length) set.headers["access-control-allow-origin"] = headers.join(", "); }; const handleMethod = (set, method) => { if (!method) return; if (methods === true) return set.headers["access-control-allow-methods"] = method ?? "*"; if (methods === false || !methods?.length) return; if (methods === "*") return set.headers["access-control-allow-methods"] = "*"; if (!Array.isArray(methods)) return set.headers["access-control-allow-methods"] = methods; set.headers["access-control-allow-methods"] = methods.join(", "); }; const defaultHeaders = {}; if (typeof exposeHeaders === "string") defaultHeaders["access-control-expose-headers"] = exposeHeaders; if (typeof allowedHeaders === "string") defaultHeaders["access-control-allow-headers"] = allowedHeaders; if (credentials === true) defaultHeaders["access-control-allow-credentials"] = "true"; app.headers(defaultHeaders); function handleOption({ set, request, headers }) { handleOrigin(set, request); handleMethod(set, request.headers.get("access-control-request-method")); if (allowedHeaders === true || exposeHeaders === true) { if (allowedHeaders === true) set.headers["access-control-allow-headers"] = headers["access-control-request-headers"]; if (exposeHeaders === true) set.headers["access-control-expose-headers"] = Object.keys(headers).join(","); } if (maxAge) set.headers["access-control-max-age"] = maxAge.toString(); return new Response(null, { status: 204 }); } if (preflight) app.options("/", handleOption).options("/*", handleOption); return app.onRequest(function processCors({ set, request }) { handleOrigin(set, request); handleMethod(set, request.method); if (allowedHeaders === true || exposeHeaders === true) { const headers = processHeaders(request.headers); if (allowedHeaders === true) set.headers["access-control-allow-headers"] = headers; if (exposeHeaders === true) set.headers["access-control-expose-headers"] = headers; } }); }; var index_default = cors; export { cors, index_default as default };