一、HTTP 单连接与多连接
1. 单连接模式 (HTTP/1.1 默认)
特点:
同一域名下所有请求共享一个TCP连接
请求必须按顺序发送和接收(队头阻塞问题)
通过
Connection: keep-alive
保持长连接
示例:
客户端: GET /resource1
服务器: 响应1
客户端: GET /resource2 (必须等待响应1完成)
服务器: 响应2
2. 多连接模式
HTTP/1.1 解决方案:
浏览器为同一域名打开多个TCP连接(通常6-8个)
并行发送请求,缓解队头阻塞
HTTP/2 多路复用:
单一TCP连接上并行交错传输多个请求/响应
二进制分帧层解决队头阻塞
请求/响应可以交错,不受顺序限制
对比表:
特性 | HTTP/1.1 单连接 | HTTP/1.1 多连接 | HTTP/2 |
---|---|---|---|
连接数 | 1 | 6-8 | 1 |
队头阻塞 | 严重 | 部分缓解 | 完全解决 |
资源开销 | 低 | 高 | 低 |
服务器压力 | 低 | 高 | 低 |
二、HTTP 预检请求 (Preflight Request)
1. 什么是预检请求
预检请求是浏览器在发送某些跨域请求前,先使用 OPTIONS
方法发起一个预检请求,以确定实际请求是否安全的机制。
2. 触发预检的条件
当请求满足以下任一条件时,浏览器会发送预检请求:
使用特定HTTP方法:
非简单方法:PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH
设置了非简单头部字段:
非简单头部:除以下之外的头部
Accept
Accept-Language
Content-Language
Content-Type(仅限特定值)
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type 非简单值:
非以下类型:
text/plain
、multipart/form-data
、application/x-www-form-urlencoded
3. 预检请求示例
客户端发送OPTIONS预检:
OPTIONS /resource HTTP/1.1
Host: api.example.com
Origin: https://yourdomain.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: X-Custom-Header
服务器响应:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://yourdomain.com
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 86400
4. 预检请求工作流程
浏览器检测到需要预检的跨域请求
先发送OPTIONS请求进行预检
服务器响应是否允许实际请求
如果允许,浏览器发送实际请求
服务器响应实际请求
5. 避免预检的方法
使用简单请求:
GET/HEAD/POST方法
仅使用简单头部
Content-Type为简单类型
利用缓存:
设置
Access-Control-Max-Age
头部
Access-Control-Max-Age: 86400 // 缓存1天
后端配置CORS:
正确配置
Access-Control-Allow-*
头部处理OPTIONS请求
三、实际开发中的场景示例
1. 触发预检的请求
// 自定义头部触发预检
fetch('https://api.example.com/data', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': 'abc123' // 自定义头部
},
body: JSON.stringify({ key: 'value' })
});
2. 不触发预检的简单请求
// 简单GET请求
fetch('https://api.example.com/data');
// 简单POST表单请求
fetch('https://api.example.com/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'key1=value1&key2=value2'
});
3. Node.js 服务端CORS配置示例
// Express 中间件
app.use((req, res, next) => {
// 允许的源
res.setHeader('Access-Control-Allow-Origin', 'https://yourdomain.com');
// 允许的方法
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
// 允许的头部
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization');
// 预检请求缓存时间
res.setHeader('Access-Control-Max-Age', '86400');
// 处理预检请求
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
理解这些机制有助于优化Web应用性能(通过合理使用连接)和正确处理跨域请求(通过理解预检机制)。