@uploadx/core
Version:
Node.js resumable upload middleware
98 lines (97 loc) • 3.84 kB
JavaScript
"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;