每天一个npm包:koa-cors
每天一个npm包:koa-cors
野生码农。公众号:NodeJs 早早聊
koa-cors
顾名思义koa-cors,是Koa框架用于解决CORS中间件的方案。通过阅读其源码,你会学会服务端CORS相关知识。
源码
koa-cors使用示例:
const Koa = require('koa');
const cors = require('@koa/cors');
const app = new Koa();
app.use(cors());
直接看代码实现
'use strict';
const vary = require('vary');
/**
* CORS middleware
*
* @param {Object} [options] 配置对象参数解释
* - {String|Function(ctx)} origin `Access-Control-Allow-Origin`, default is request Origin header
* - {String|Array} allowMethods `Access-Control-Allow-Methods`, default is 'GET,HEAD,PUT,POST,DELETE,PATCH'
* - {String|Array} exposeHeaders `Access-Control-Expose-Headers`
* - {String|Array} allowHeaders `Access-Control-Allow-Headers`
* - {String|Number} maxAge `Access-Control-Max-Age` in seconds
* - {Boolean} credentials `Access-Control-Allow-Credentials`
* - {Boolean} keepHeadersOnError Add set headers to `err.header` if an error is thrown
* @return {Function} cors middleware
* @api public
*/
module.exports = function(options) {
// 默认配置
const defaults = {
// Access-Control-Allow-Methods 必须字段,表示服务器支持的跨域HTTP方法、返回的是所有支持方法
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
};
// 合并option、defaults默认配置允许被覆盖
options = {
...defaults,
...options,
};
// 组装options
// CORS很多响应头value都是允许多个逗号分隔的字符串
if (Array.isArray(options.exposeHeaders)) {
options.exposeHeaders = options.exposeHeaders.join(',');
}
if (Array.isArray(options.allowMethods)) {
options.allowMethods = options.allowMethods.join(',');
}
if (Array.isArray(options.allowHeaders)) {
options.allowHeaders = options.allowHeaders.join(',');
}
if (options.maxAge) {
options.maxAge = String(options.maxAge);
}
options.keepHeadersOnError = options.keepHeadersOnError === undefined || !!options.keepHeadersOnError;
// 返回Koa中间件
return async function cors(ctx, next) {
// If the Origin header is not present terminate this set of steps.
// The request is outside the scope of this specification.
// 默认获取的是ctx.request.origin
const requestOrigin = ctx.get('Origin');
// Always set Vary header
// https://github.com/rs/cors/issues/10
ctx.vary('Origin');
// 如果没有origin头、直接终止流程
if (!requestOrigin) return await next();
// 处理不同情况下origin的获取
let origin;
if (typeof options.origin === 'function') {
origin = options.origin(ctx);
if (origin