CORS 中间件
CORS 是一个用于 Express/Connect 的 Node.js 中间件,用于设置 CORS 响应头。这些响应头告诉浏览器哪些来源可以读取你服务器的响应。
🌐 CORS is a Node.js middleware for Express/Connect that sets CORS response headers. These headers tell browsers which origins can read responses from your server.
Note
CORS 的工作原理: 这个包设置响应头——它不会阻止请求。CORS 由浏览器执行:浏览器会检查头信息并决定 JavaScript 是否可以读取响应。非浏览器客户端(curl、Postman、其他服务器)完全忽略 CORS。详情请参见 MDN CORS 指南。
安装
🌐 Installation
这是一个可以通过npm注册表获取的Node.js模块。安装可以使用npm install命令完成:
🌐 This is a Node.js module available through the
npm registry. Installation is done using the
npm install command:
npm install corsyarn add corspnpm add corsbun add corsNote
cors 不包含其自身的 TypeScript 类型定义。如果你使用 TypeScript,还需要作为开发依赖从 DefinitelyTyped 安装社区维护的类型:
npm install --save-dev @types/corsyarn add --dev @types/corspnpm add --save-dev @types/corsbun add --dev @types/cors使用
🌐 Usage
简单使用(启用 所有 CORS 请求)
🌐 Simple Usage (Enable All CORS Requests)
var express = require('express');var cors = require('cors');var app = express();
// Adds headers: Access-Control-Allow-Origin: *app.use(cors());
app.get('/products/:id', function (req, res, next) { res.json({ msg: 'Hello' });});
app.listen(80, function () { console.log('web server listening on port 80');});为单一路由启用 CORS
🌐 Enable CORS for a Single Route
var express = require('express');var cors = require('cors');var app = express();
// Adds headers: Access-Control-Allow-Origin: *app.get('/products/:id', cors(), function (req, res, next) { res.json({ msg: 'Hello' });});
app.listen(80, function () { console.log('web server listening on port 80');});配置 CORS
🌐 Configuring CORS
有关详细信息,请参阅配置选项。
🌐 See the configuration options for details.
var express = require('express');var cors = require('cors');var app = express();
var corsOptions = { origin: 'http://example.com', optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204};
// Adds headers: Access-Control-Allow-Origin: http://example.com, Vary: Originapp.get('/products/:id', cors(corsOptions), function (req, res, next) { res.json({ msg: 'Hello' });});
app.listen(80, function () { console.log('web server listening on port 80');});配置具有动态源的 CORS
🌐 Configuring CORS w/ Dynamic Origin
此模块支持使用提供给 origin 选项的函数动态验证来源。该函数将接收一个字符串,该字符串是来源(如果请求没有来源,则为 undefined),以及一个 callback,其签名为 callback(error, origin)。
🌐 This module supports validating the origin dynamically using a function provided
to the origin option. This function will be passed a string that is the origin
(or undefined if the request has no origin), and a callback with the signature
callback(error, origin).
origin 参数传给回调时可以是中间件的 origin 选项允许的任何值,但不能是函数。有关所有可能值类型的更多信息,请参见 配置选项 部分。
🌐 The origin argument to the callback can be any value allowed for the origin
option of the middleware, except a function. See the
configuration options section for more information on all
the possible value types.
此功能旨在允许从支持的数据源(如数据库)动态加载允许的来源。
🌐 This function is designed to allow the dynamic loading of allowed origin(s) from a backing datasource, like a database.
var express = require('express');var cors = require('cors');var app = express();
var corsOptions = { origin: function (origin, callback) { // db.loadOrigins is an example call to load // a list of origins from a backing database db.loadOrigins(function (error, origins) { callback(error, origins); }); },};
// Adds headers: Access-Control-Allow-Origin: <matched origin>, Vary: Originapp.get('/products/:id', cors(corsOptions), function (req, res, next) { res.json({ msg: 'Hello' });});
app.listen(80, function () { console.log('web server listening on port 80');});启用 CORS 预检
🌐 Enabling CORS Pre-Flight
某些 CORS 请求被认为是“复杂”的,需要一个初始的 OPTIONS 请求(称为“预检请求”)。一个“复杂” CORS 请求的例子是使用 GET/HEAD/POST 以外的 HTTP 方法(例如 DELETE)或使用自定义头。要启用预检,必须为你想要支持的路由添加一个新的 OPTIONS 处理程序:
🌐 Certain CORS requests are considered ‘complex’ and require an initial
OPTIONS request (called the “pre-flight request”). An example of a
‘complex’ CORS request is one that uses an HTTP verb other than
GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable
pre-flighting, you must add a new OPTIONS handler for the route you want
to support:
var express = require('express');var cors = require('cors');var app = express();
app.options('/products/:id', cors()); // preflight for DELETEapp.delete('/products/:id', cors(), function (req, res, next) { res.json({ msg: 'Hello' });});
app.listen(80, function () { console.log('web server listening on port 80');});你也可以像这样启用全方位的预检:
🌐 You can also enable pre-flight across-the-board like so:
app.options('*', cors()); // include before other routes注意:当将此中间件作为应用级中间件使用时(例如 app.use(cors())),所有路由的预检请求已经被处理。
🌐 NOTE: When using this middleware as an application level middleware (for
example, app.use(cors())), pre-flight requests are already handled for all
routes.
根据每个请求动态自定义 CORS 设置
🌐 Customizing CORS Settings Dynamically per Request
对于需要针对特定路由或请求配置不同 CORS 设置的 API,你可以根据传入的请求动态生成 CORS 选项。cors 中间件允许你通过传递一个函数而不是静态选项来实现这一点。这个函数会在每个传入请求时被调用,并且必须使用回调模式返回适当的 CORS 选项。
🌐 For APIs that require different CORS configurations for specific routes or requests, you can dynamically generate CORS options based on the incoming request. The cors middleware allows you to achieve this by passing a function instead of static options. This function is called for each incoming request and must use the callback pattern to return the appropriate CORS options.
该函数接受:
🌐 The function accepts:
req:- 传入的请求对象。
callback(error, corsOptions):- 用于返回计算后的 CORS 选项的函数。
- 参数:
error:如果没有错误,则传递null;如果发生错误,则传递一个错误对象以指示失败。corsOptions:一个指定当前请求 CORS 策略的对象。
这是一个处理公共路由和受限、需凭证的路由的示例:
🌐 Here’s an example that handles both public routes and restricted, credential-sensitive routes:
var dynamicCorsOptions = function (req, callback) { var corsOptions; if (req.path.startsWith('/auth/connect/')) { // Access-Control-Allow-Origin: http://mydomain.com, Access-Control-Allow-Credentials: true, Vary: Origin corsOptions = { origin: 'http://mydomain.com', credentials: true, }; } else { // Access-Control-Allow-Origin: * corsOptions = { origin: '*' }; } callback(null, corsOptions);};
app.use(cors(dynamicCorsOptions));
app.get('/auth/connect/twitter', function (req, res) { res.send('Hello');});
app.get('/public', function (req, res) { res.send('Hello');});
app.listen(80, function () { console.log('web server listening on port 80');});配置选项
🌐 Configuration Options
origin:配置 Access-Control-Allow-Origin CORS 头。可能的值:Boolean- 将origin设置为true以反映由req.header('Origin')定义的 请求来源,或将其设置为false以禁用 CORS。String- 将origin设置为特定来源。例如,如果你将其设置为"http://example.com"只允许来自 “http://example.com” 的请求。"*"允许所有域名。
RegExp- 将origin设置为一个正则表达式模式,该模式将用于测试请求的来源。如果匹配,请求来源将被反映。例如,模式/example\.com$/将反映来自以“example.com”结尾的来源的任何请求。Array- 将origin设置为有效来源的数组。每个来源可以是String或RegExp。例如,["http://example1.com", /\.example2\.com$/]将接受来自 “http://example1.com” 或来自 “example2.com” 子域的任何请求。Function- 将origin设置为实现某些自定义逻辑的函数。该函数将请求来源作为第一个参数,将回调(作为callback(err, origin)调用,其中origin是origin选项的非函数值)作为第二个参数。
methods:配置 Access-Control-Allow-Methods CORS 头。期望一个逗号分隔的字符串(例如:‘GET,PUT,POST’)或一个数组(例如:['GET', 'PUT', 'POST'])。allowedHeaders:配置 Access-Control-Allow-Headers CORS 头。期望一个逗号分隔的字符串(例如:‘Content-Type,Authorization’)或一个数组(例如:['Content-Type', 'Authorization'])。如果未指定,默认为反映请求中 Access-Control-Request-Headers 头中指定的头。exposedHeaders:配置 Access-Control-Expose-Headers CORS 头。期望一个逗号分隔的字符串(例如:‘Content-Range,X-Content-Range’)或一个数组(例如:['Content-Range', 'X-Content-Range'])。如果未指定,则不会公开任何自定义头。credentials:配置 Access-Control-Allow-Credentials CORS 头。设置为true以传递该头,否则将被省略。maxAge:配置 Access-Control-Max-Age CORS 头。设置为整数以传递该头,否则将省略。preflightContinue:将 CORS 预检响应传递给下一个处理程序。optionsSuccessStatus:为成功的OPTIONS请求提供一个状态码,因为一些旧版浏览器(IE11,各种智能电视)在204上会出错。
默认配置相当于:
🌐 The default configuration is the equivalent of:
{ "origin": "*", "methods": "GET,HEAD,PUT,PATCH,POST,DELETE", "preflightContinue": false, "optionsSuccessStatus": 204}常见误解
🌐 Common Misconceptions
CORS 阻止来自不被允许的来源的请求
🌐 “CORS blocks requests from disallowed origins”
不。 你的服务器接收并处理每一个请求。CORS 头部告诉浏览器 JavaScript 是否可以读取响应,而不是请求是否被允许。
CORS 保护我的 API 免受未经授权的访问
🌐 “CORS protects my API from unauthorized access”
不。 CORS 不是访问控制。任何 HTTP 客户端(curl、Postman、其他服务器)都可以调用你的 API,而不受 CORS 设置的限制。使用身份验证和授权来保护你的 API。
设置 origin: 'http://example.com' 意味着只有该域名可以访问我的服务器
🌐 “Setting origin: 'http://example.com' means only that domain can access my server”
不。 这意味着浏览器只会允许来自该来源的 JavaScript 读取响应。服务器仍然会对所有请求作出响应。
许可证
🌐 License
原作者
🌐 Original Author