复杂请求预检检查内容
CORS 预检请求检查的内容及服务器响应方式
问题
跨域复杂请求会触发预检请求(Preflight Request),预检请求具体检查什么内容?
解答
什么是复杂请求
满足以下任一条件的请求为复杂请求:
- 使用
PUT、DELETE、PATCH等方法 - 包含自定义请求头(如
X-Token) Content-Type不是application/x-www-form-urlencoded、multipart/form-data、text/plain
预检请求检查内容
浏览器发送 OPTIONS 请求,携带以下头部询问服务器:
| 请求头 | 作用 |
|---|---|
Origin | 请求来源 |
Access-Control-Request-Method | 实际请求将使用的方法 |
Access-Control-Request-Headers | 实际请求将携带的自定义头 |
服务器响应
服务器需返回对应的允许头:
| 响应头 | 作用 |
|---|---|
Access-Control-Allow-Origin | 允许的来源 |
Access-Control-Allow-Methods | 允许的方法 |
Access-Control-Allow-Headers | 允许的请求头 |
Access-Control-Max-Age | 预检结果缓存时间(秒) |
示例
// 前端发起复杂请求
fetch('https://api.example.com/data', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Token': 'abc123' // 自定义头,触发预检
},
body: JSON.stringify({ name: 'test' })
});
# 浏览器自动发送的预检请求
OPTIONS /data HTTP/1.1
Host: api.example.com
Origin: https://mysite.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, X-Token
# 服务器响应
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://mysite.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, X-Token
Access-Control-Max-Age: 86400
// Node.js 服务端处理示例
app.options('/data', (req, res) => {
res.set({
'Access-Control-Allow-Origin': req.headers.origin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type, X-Token',
'Access-Control-Max-Age': '86400'
});
res.status(204).end();
});
关键点
- 预检请求使用
OPTIONS方法,由浏览器自动发起 - 检查三项:来源(Origin)、请求方法、自定义请求头
- 服务器必须返回对应的
Access-Control-Allow-*头 Access-Control-Max-Age可缓存预检结果,避免重复请求- 预检通过后,浏览器才会发送实际请求
目录