UNPKG

@uploadx/core

Version:
98 lines (97 loc) 3.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.cors = exports.Cors = void 0; const utils_1 = require("../utils"); class Cors { constructor(config = {}) { this.allowedHeaders = config.allowedHeaders || []; this.allowedMethods = config.allowedMethods || []; this._allowOrigins = config.allowOrigins || []; this.credentials = config.credentials ?? false; this.exposeHeaders = config.exposeHeaders || []; this.maxAge = config.maxAge ?? 600; } set allowOrigins(value) { this._allowOrigins = value.map(allowedOrigin => { if (allowedOrigin === '*' || allowedOrigin instanceof RegExp) return allowedOrigin; if (allowedOrigin.includes('*')) return new RegExp(allowedOrigin.replace(/\*/g, '.*')); return allowedOrigin; }); } /** * Set cors headers * @returns `true` if it is a preflight request */ preflight(req, res, next) { const origin = (0, utils_1.getHeader)(req, 'origin'); if (!origin || res.getHeader('Access-Control-Allow-Origin')) return false; if (!this.isOriginAllowed(origin)) { next?.(new Error(`Access is not allowed from the origin: ${origin}`)); return true; } res.setHeader('Access-Control-Allow-Origin', origin); this.credentials && res.setHeader('Access-Control-Allow-Credentials', 'true'); const vary = [res.getHeader('vary'), 'Origin'].flat().filter(Boolean); const accessControlRequestMethod = (0, utils_1.getHeader)(req, 'access-control-request-method'); if (accessControlRequestMethod && req.method === 'OPTIONS') { // preflight res.setHeader('Access-Control-Allow-Methods', this.allowedMethods.join() || accessControlRequestMethod); const accessControlRequestHeaders = (0, utils_1.getHeader)(req, 'access-control-request-headers', true); const allowedHeaders = this.allowedHeaders.join() || accessControlRequestHeaders; allowedHeaders && res.setHeader('Access-Control-Allow-Headers', allowedHeaders); !this.allowedHeaders.length && vary.push('Access-Control-Request-Headers'); !this.allowedMethods.length && vary.push('Access-Control-Request-Method'); res.setHeader('Vary', vary.join()); res.setHeader('Access-Control-Max-Age', this.maxAge); return true; } // actual res.setHeader('Vary', vary.join()); this.exposeHeaders.length && res.setHeader('Access-Control-Expose-Headers', this.exposeHeaders.join()); return false; } /** * Check if origin allowed */ isOriginAllowed(origin) { if (this._allowOrigins.length === 0) return true; return this._allowOrigins.some(allowedOrigin => { return (allowedOrigin === origin || allowedOrigin === '*' || (allowedOrigin instanceof RegExp && allowedOrigin.test(origin))); }); } } exports.Cors = Cors; const defaultCorsConfig = { allowedHeaders: [], allowedMethods: ['GET', 'POST', 'HEAD', 'PUT', 'DELETE', 'PATCH'], allowOrigins: [], credentials: false, exposeHeaders: [], maxAge: 600 }; /** * CORS middleware for Node.js. * @example * ```ts * app.use(cors({ allowOrigins: ['*'], exposeHeaders: ['Authorization, ETag'] })); * ``` */ const cors = (config = {}) => { const _cors = new Cors({ ...defaultCorsConfig, ...config }); return (req, res, next) => { if (_cors.preflight(req, res, next)) { res.writeHead(204, { 'Content-Length': 0 }).end(); } else { next?.(); } }; }; exports.cors = cors;