什么是Header、缓存、CORS 与协议进化?

HTTP Header
HTTP Header(HTTP 头部)的作用,可以用一句话概括:
HTTP Header 用来携带额外的元数据,让客户端与服务器能够更精确、更灵活地沟通。
它不传输主体内容(如 HTML、JSON、图片),而是传输“关于这次请求/响应的说明和规则”。
- • 用户是谁
- • 浏览器是什么类型
- • 内容的格式和编码方式
- • 是否启用缓存
- • 是否需要认证
- • 连接是否保持
- • 服务端运行的程序类型
这些都通过 Header 来描述的。
通用 Header
Date
Date: Mon, 20 Nov 2024 12:00:00 GMT消息发送的日期和时间
Connection
Connection: keep-aliveConnection: close控制连接是否保持
Cache-Control
Cache-Control: no-cacheCache-Control: max-age=3600Cache-Control: public, max-age=86400缓存指令
Transfer-Encoding
Transfer-Encoding: chunked传输编码方式
请求 Header
Host(必需)
Host: www.example.com指定服务器的域名和端口
User-Agent
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0客户端信息
Accept
Accept: text/html,application/jsonAccept: */*客户端可接受的内容类型
Accept-Encoding
Accept-Encoding: gzip, deflate, br客户端支持的压缩方式
Accept-Language
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8客户端偏好的语言
Referer
Referer: https://www.google.com/search?q=http请求来源页面
Cookie
Cookie: sessionId=abc123; userId=456发送给服务器的 Cookie
Authorization
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=身份认证信息
If-Modified-Since
If-Modified-Since: Mon, 01 Jan 2024 00:00:00 GMT条件请求,用于缓存验证
If-None-Match
If-None-Match: "686897696a7c876b7e"条件请求,与 ETag 配合
Range
Range: bytes=0-1023请求部分内容,用于断点续传
响应 Header
Content-Type
Content-Type: text/html; charset=utf-8Content-Type: application/jsonContent-Type: image/png响应内容的媒体类型
Content-Length
Content-Length: 3495响应体的字节数
Content-Encoding
Content-Encoding: gzip响应体的压缩方式
Content-Language
Content-Language: zh-CN响应内容的语言
Location
Location: https://www.example.com/new-page重定向的目标 URL
Set-Cookie
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; SecureSet-Cookie: userId=456; Max-Age=3600; Domain=.example.com设置 Cookie
Last-Modified
Last-Modified: Mon, 01 Jan 2024 00:00:00 GMT资源最后修改时间
ETag
ETag: "686897696a7c876b7e"资源的唯一标识符
Expires
Expires: Mon, 27 Nov 2024 12:00:00 GMT响应过期时间
Age
Age: 3600资源在缓存中存在的时间(秒)
安全相关 Header
Strict-Transport-Security
Strict-Transport-Security: max-age=31536000; includeSubDomains强制使用 HTTPS(HSTS)
X-Frame-Options
X-Frame-Options: DENYX-Frame-Options: SAMEORIGIN防止点击劫持
X-Content-Type-Options
X-Content-Type-Options: nosniff防止 MIME 类型嗅探
X-XSS-Protection
X-XSS-Protection: 1; mode=block启用 XSS 过滤
Content-Security-Policy
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'内容安全策略
Referrer-Policy
Referrer-Policy: no-referrer-when-downgrade控制 Referer 信息的发送
CORS 相关 Header
Access-Control-Allow-Origin
Access-Control-Allow-Origin: *Access-Control-Allow-Origin: https://example.com允许的源
Access-Control-Allow-Methods
Access-Control-Allow-Methods: GET, POST, PUT, DELETE允许的方法
Access-Control-Allow-Headers
Access-Control-Allow-Headers: Content-Type, Authorization允许的请求头
Access-Control-Allow-Credentials
Access-Control-Allow-Credentials: true是否允许发送 Cookie
Access-Control-Max-Age
Access-Control-Max-Age: 86400预检请求的缓存时间
HTTP 缓存
缓存的作用
- • 减少网络带宽消耗
- • 降低服务器负载
- • 加快页面加载速度
- • 提升用户体验
缓存类型
1. 强缓存
不需要向服务器发送请求,直接使用缓存。
Expires(HTTP/1.0):
Expires: Mon, 27 Nov 2024 12:00:00 GMT绝对时间,受客户端时间影响
Cache-Control(HTTP/1.1,优先级更高):
Cache-Control: max-age=3600相对时间,更可靠
Cache-Control 指令:
max-age=秒数 # 缓存最大有效时间s-maxage=秒数 # 代理服务器缓存时间public # 可被任何缓存存储private # 只能被浏览器缓存no-cache # 需要验证后才能使用缓存no-store # 不缓存任何内容must-revalidate # 过期后必须验证2. 协商缓存
需要向服务器验证缓存是否有效。
Last-Modified / If-Modified-Since:
首次请求:
响应:HTTP/1.1 200 OKLast-Modified: Mon, 01 Jan 2024 00:00:00 GMT后续请求:
请求:GET /image.jpg HTTP/1.1If-Modified-Since: Mon, 01 Jan 2024 00:00:00 GMT响应(未修改):HTTP/1.1 304 Not Modified响应(已修改):HTTP/1.1 200 OKLast-Modified: Mon, 02 Jan 2024 00:00:00 GMTETag / If-None-Match:
首次请求:
响应:HTTP/1.1 200 OKETag: "686897696a7c876b7e"后续请求:
请求:GET /image.jpg HTTP/1.1If-None-Match: "686897696a7c876b7e"响应(未修改):HTTP/1.1 304 Not Modified响应(已修改):HTTP/1.1 200 OKETag: "786897696a7c876b7f"缓存策略
不同资源的缓存策略:
# HTML 文件:不缓存或短时间缓存Cache-Control: no-cacheCache-Control: max-age=300# CSS/JS 文件(带版本号或 hash):长期缓存Cache-Control: public, max-age=31536000, immutable# 图片:中等时间缓存Cache-Control: public, max-age=86400# API 响应:不缓存或短时间缓存Cache-Control: no-cacheCache-Control: private, max-age=60完整的缓存流程:
1. 浏览器请求资源2. 检查是否有强缓存且未过期 是 → 直接使用缓存(200 from cache) 否 → 继续3. 检查是否有协商缓存标识 无 → 直接请求服务器 有 → 发送条件请求(If-Modified-Since 或 If-None-Match)4. 服务器判断资源是否修改 未修改 → 返回 304 已修改 → 返回 200 和新资源跨域资源共享(CORS)
CORS(Cross-Origin Resource Sharing,跨域资源共享)是浏览器为解决“跨域问题”而设计的一套安全机制,它允许服务器明确告诉浏览器:哪些域名可以访问其资源、允许使用哪些请求方法、是否允许携带 Cookie 等。由于浏览器默认出于安全考虑禁止网页跨域读取资源,而现代前后端分离、多服务交互的场景又大量依赖跨域访问,CORS 就成为标准的解决方案。
简单来说,CORS 就是服务器通过一系列 HTTP Header(如 Access-Control-Allow-Origin)来声明访问权限,浏览器根据这些规则决定是否放行跨域请求,既保证了网络安全,又让跨域通信成为可能。
同源策略
浏览器的同源策略限制了不同源之间的资源访问。
同源定义:
协议 + 域名 + 端口 完全相同同源示例:https://example.com:443/page1https://example.com:443/page2跨域示例:https://example.com(协议不同)http://api.example.com(子域名不同)https://example.com:8080(端口不同)受限制的操作:
- • AJAX 请求
- • Cookie、LocalStorage、IndexedDB 访问
- • DOM 访问
不受限制的操作:
- • 图片、CSS、JavaScript 的加载
- • 表单提交
CORS 工作原理
简单请求:
满足以下条件的请求:
- • 方法:GET、HEAD、POST
- • Header:Accept、Accept-Language、Content-Language、Content-Type(限定值)
- • Content-Type:text/plain、multipart/form-data、application/x-www-form-urlencoded
示例:
请求:GET /api/data HTTP/1.1Origin: https://example.com响应:HTTP/1.1 200 OKAccess-Control-Allow-Origin: https://example.comAccess-Control-Allow-Credentials: true预检请求(Preflight):
不满足简单请求条件时,浏览器先发送 OPTIONS 请求。
预检请求:OPTIONS /api/data HTTP/1.1Origin: https://example.comAccess-Control-Request-Method: PUTAccess-Control-Request-Headers: Content-Type预检响应:HTTP/1.1 200 OKAccess-Control-Allow-Origin: https://example.comAccess-Control-Allow-Methods: GET, POST, PUT, DELETEAccess-Control-Allow-Headers: Content-TypeAccess-Control-Max-Age: 86400实际请求:PUT /api/data HTTP/1.1Origin: https://example.comContent-Type: application/json实际响应:HTTP/1.1 200 OKAccess-Control-Allow-Origin: https://example.comCORS 配置
服务器端配置(Node.js):
const express = require('express');const cors = require('cors');const app = express();// 方式 1:允许所有源app.use(cors());// 方式 2:配置特定源app.use(cors({ origin: 'https://example.com', credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'], exposedHeaders: ['X-Total-Count'], maxAge: 86400}));// 方式 3:动态配置app.use(cors({ origin: function(origin, callback) { const allowedOrigins = ['https://example.com', 'https://app.example.com']; if (!origin || allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } }}));// 方式 4:手动设置 Headerapp.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://example.com'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.header('Access-Control-Allow-Credentials', 'true'); if (req.method === 'OPTIONS') { return res.sendStatus(200); } next();});Nginx 配置:
server { listen 80; server_name api.example.com; location / { # 允许的源 add_header Access-Control-Allow-Origin https://example.com always; # 允许的方法 add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always; # 允许的 Header add_header Access-Control-Allow-Headers "Content-Type, Authorization" always; # 允许携带 Cookie add_header Access-Control-Allow-Credentials true always; # 预检请求缓存时间 add_header Access-Control-Max-Age 86400 always; # 处理 OPTIONS 请求 if ($request_method = 'OPTIONS') { return 204; } proxy_pass http://backend; }}其他跨域解决方案
1. JSONP(仅支持 GET):
// 客户端function handleResponse(data) { console.log(data);}const script = document.createElement('script');script.src = 'https://api.example.com/data?callback=handleResponse';document.body.appendChild(script);// 服务器端app.get('/data', (req, res) => { const callback = req.query.callback; const data = { name: 'John', age: 30 }; res.send(`${callback}(${JSON.stringify(data)})`);});2. 代理服务器:
// 开发环境代理配置(Webpack)module.exports = { devServer: { proxy: { '/api': { target: 'https://api.example.com', changeOrigin: true, pathRewrite: { '^/api': '' } } } }};// Nginx 反向代理server { listen 80; server_name example.com; location /api/ { proxy_pass https://api.example.com/; } location / { root /var/www/html; }}3. postMessage(用于 iframe 通信):
// 父页面iframe.contentWindow.postMessage('Hello', 'https://child.example.com');// 子页面window.addEventListener('message', (event) => { if (event.origin === 'https://parent.example.com') { console.log(event.data); // 'Hello' }});HTTP/2 和 HTTP/3
HTTP 的演进始于 1991 年的 HTTP/0.9,那时它只是为传输简单的 HTML 文档而设计,只有一个 GET 方法,没有状态码、没有 Header,也不支持媒体类型。随后 1996 年发布的 HTTP/1.0 引入了请求头、响应头、状态码、多媒体类型、缓存机制,使 Web 的表达能力大幅提升。1997 年的 HTTP/1.1 则奠定了现代 Web 的基础:持久连接(Keep-Alive)、管道化、分块传输、强缓存/弱缓存、Host 头等关键特性,让网站能更快、更稳定、更复杂,也使它长期成为最主流的 HTTP 版本。
随着 Web 页面越来越重、资源请求数量激增,HTTP/1.1 的队头阻塞问题变得突出,于是出现了 HTTP/2。它基于二进制帧、多路复用、头部压缩、服务器推送等特性,大幅提升性能。为适应移动网络与高延迟场景,谷歌提出 QUIC 协议,并成为 HTTP/3 的基础,彻底摆脱 TCP 的队头阻塞,提供更快的连接建立、更强的丢包恢复能力。HTTP 的演进贯穿整个互联网发展史,从简单的文本传输工具成长为现代 Web 的高性能基础设施。
HTTP/2
HTTP/2 于 2015 年发布,是 HTTP 协议的重大更新。
主要特性:
1. 二进制分帧
HTTP/1.x 使用文本格式,HTTP/2 使用二进制格式。
HTTP/1.1(文本):GET /index.html HTTP/1.1Host: example.comHTTP/2(二进制):[二进制帧数据]2. 多路复用
在一个 TCP 连接上并发多个请求/响应。
HTTP/1.1:连接 1:请求 A → 响应 A连接 2:请求 B → 响应 B连接 3:请求 C → 响应 CHTTP/2:连接 1:请求 A、B、C → 响应 A、B、C(交错传输)优点:
- • 不需要多个 TCP 连接
- • 避免队头阻塞
- • 减少网络拥塞
3. Header 压缩
使用 HPACK 算法压缩 Header。
首次请求::method: GET:path: /index.html:authority: example.comuser-agent: Mozilla/5.0...后续请求::method: GET:path: /style.css:authority: [索引 2] # 引用之前发送的值user-agent: [索引 4]4. 服务器推送
服务器可以主动推送资源。
客户端请求:GET /index.html服务器响应:返回 index.html同时推送:style.css, script.js, logo.png5. 流优先级
可以设置资源的优先级。
优先级:1. 关键 CSS(高)2. 关键 JavaScript(高)3. 图片(中)4. 分析脚本(低)HTTP/2 示例:
// Node.js HTTP/2 服务器const http2 = require('http2');const fs = require('fs');const server = http2.createSecureServer({ key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem')});server.on('stream', (stream, headers) => { // 服务器推送 stream.pushStream({ ':path': '/style.css' }, (err, pushStream) => { pushStream.respond({ ':status': 200 }); pushStream.end(fs.readFileSync('style.css')); }); // 主响应 stream.respond({ 'content-type': 'text/html', ':status': 200 }); stream.end('<html><body>Hello HTTP/2</body></html>');});server.listen(443);HTTP/3
HTTP/3 于 2022 年标准化,基于 QUIC 协议。
主要改进:
1. 基于 UDP
HTTP/3 使用 QUIC(基于 UDP),而不是 TCP。
HTTP/2:TCP + TLS + HTTP/2HTTP/3:UDP + QUIC + HTTP/32. 更快的连接建立
QUIC 将 TLS 握手集成到传输层。
TCP + TLS(3-RTT):TCP 握手(1-RTT)→ TLS 握手(2-RTT)QUIC(1-RTT):QUIC 握手(包含 TLS)3. 解决队头阻塞
TCP 的队头阻塞问题在 HTTP/3 中得到解决。
TCP(HTTP/2):丢包 → 阻塞所有流 → 等待重传QUIC(HTTP/3):丢包 → 只阻塞该流 → 其他流继续传输4. 连接迁移
支持 IP 地址变化(如从 WiFi 切换到移动网络)。
客户端 IP 变化(192.168.1.100 → 192.168.2.100)连接标识符不变 → 连接继续有效5. 内置加密
QUIC 原生支持加密,无需单独的 TLS 层。
HTTP/3 配置(Nginx):
server { listen 443 ssl http2; listen 443 quic reuseport; # HTTP/3 server_name example.com; # 添加 Alt-Svc Header add_header Alt-Svc 'h3=":443"; ma=86400'; ssl_certificate cert.pem; ssl_certificate_key key.pem; location / { root /var/www/html; }}HTTP 版本对比
| 特性 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| 传输层 | TCP | TCP | UDP (QUIC) |
| 文本/二进制 | 文本 | 二进制 | 二进制 |
| 多路复用 | 否 | 是 | 是 |
| Header 压缩 | 否 | HPACK | QPACK |
| 服务器推送 | 否 | 是 | 是 |
| 队头阻塞 | 是 | 部分 | 否 |
| 连接迁移 | 否 | 否 | 是 |
| 握手延迟 | 3-RTT | 3-RTT | 1-RTT |
当前 HTTP/3 已经从概念阶段逐步迈入主流部署阶段:多数现代浏览器(包括 Chrome、Firefox、Safari)都支持 HTTP/3,据不完全统计,全球前千万网站中约有 30% 已启用 HTTP/3。它利用 QUIC(基于 UDP 的传输协议)替代传统 TCP,从而减少连接建立时间、缓解队头阻塞、提升丢包环境下的性能。
但也别以为它已经“全面成熟”:尽管部署速度快,许多网站仍兼容 HTTP/2 或 HTTP/1.1,而且 HTTP/3 的性能优势在实际中依旧受多种因素制约,例如服务器支持、网络条件、第三方资源是否也支持 HTTP/3 等。换句话说,它是未来方向,但如果你当前的系统还未实现,延迟切换也不至于“马上掉队”,但确实值得认真考虑导入。
本文内容仅供参考,不构成任何专业建议。使用本文提供的信息时,请自行判断并承担相应风险。



