koa2-cors
Version:
cors middleware for koa2
98 lines (85 loc) • 3.11 kB
JavaScript
/**
* CORS middleware for koa2
*
* @param {Object} [options]
* - {String|Function(ctx)} origin `Access-Control-Allow-Origin`, default is request Origin header
* - {Array} exposeHeaders `Access-Control-Expose-Headers`
* - {String|Number} maxAge `Access-Control-Max-Age` in seconds
* - {Boolean} credentials `Access-Control-Allow-Credentials`
* - {Array} allowMethods `Access-Control-Allow-Methods`,
* default is ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']
* - {Array} allowHeaders `Access-Control-Allow-Headers`
* @return {Function}
* @api public
*/
module.exports = function crossOrigin(options = {}) {
const defaultOptions = {
allowMethods: ['GET', 'PUT', 'POST', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
};
// set defaultOptions to options
options = Object.assign({}, defaultOptions, options); // eslint-disable-line no-param-reassign
// eslint-disable-next-line consistent-return
return async function cors(ctx, next) {
// always set vary Origin Header
// https://github.com/rs/cors/issues/10
ctx.vary('Origin');
let origin;
if (typeof options.origin === 'function') {
origin = options.origin(ctx);
} else {
origin = options.origin || ctx.get('Origin') || '*';
}
if (!origin) {
return await next();
}
// Access-Control-Allow-Origin
ctx.set('Access-Control-Allow-Origin', origin);
if (ctx.method === 'OPTIONS') {
// Preflight Request
if (!ctx.get('Access-Control-Request-Method')) {
return await next();
}
// Access-Control-Max-Age
if (options.maxAge) {
ctx.set('Access-Control-Max-Age', String(options.maxAge));
}
// Access-Control-Allow-Credentials
if (options.credentials === true) {
// When used as part of a response to a preflight request,
// this indicates whether or not the actual request can be made using credentials.
ctx.set('Access-Control-Allow-Credentials', 'true');
}
// Access-Control-Allow-Methods
if (options.allowMethods) {
ctx.set('Access-Control-Allow-Methods', options.allowMethods.join(','));
}
// Access-Control-Allow-Headers
if (options.allowHeaders) {
ctx.set('Access-Control-Allow-Headers', options.allowHeaders.join(','));
} else {
ctx.set('Access-Control-Allow-Headers', ctx.get('Access-Control-Request-Headers'));
}
ctx.status = 204; // No Content
} else {
// Request
// Access-Control-Allow-Credentials
if (options.credentials === true) {
if (origin === '*') {
// `credentials` can't be true when the `origin` is set to `*`
ctx.remove('Access-Control-Allow-Credentials');
} else {
ctx.set('Access-Control-Allow-Credentials', 'true');
}
}
// Access-Control-Expose-Headers
if (options.exposeHeaders) {
ctx.set('Access-Control-Expose-Headers', options.exposeHeaders.join(','));
}
try {
await next();
} catch (err) {
throw err;
}
}
};
};