HTTP 头部详细说明

文章目录

一、通用头部

1. Cache-Control

作用:控制缓存机制的核心头部,指示请求和响应中的所有缓存机制。

详细说明:

复制代码
Cache-Control: public, max-age=3600, must-revalidate

指令类型

可缓存性指令:
  • public:响应可以被任何缓存(浏览器、代理服务器、CDN)缓存
  • private:响应只能被用户浏览器缓存,不允许共享缓存(如CDN)存储
  • no-cache:必须先向服务器验证(发送条件请求)才能使用缓存
  • no-store:禁止缓存任何响应内容,每次都必须从服务器获取
到期指令:
  • max-age=<seconds>:资源被认为新鲜的最大秒数(相对于请求时间)
  • s-maxage=<seconds>:仅适用于共享缓存(如代理服务器),覆盖max-age
  • max-stale[=<seconds>]:客户端愿意接受过期但不超过指定秒数的响应
  • min-fresh=<seconds>:客户端希望获取在指定秒数内保持新鲜的响应
重新验证和重新加载指令:
  • must-revalidate:一旦缓存过期,必须向源服务器验证
  • proxy-revalidate:与must-revalidate相同,但仅适用于共享缓存
  • immutable:表示响应内容永不变,浏览器可以直接使用缓存而不验证
其他指令:
  • no-transform:禁止代理服务器转换资源(如压缩图片)
  • only-if-cached:只从缓存获取,不请求网络,如果无缓存则返回504

应用示例

复制代码
# 静态资源可以缓存一年
Cache-Control: public, max-age=31536000, immutable

# 需要经常验证的用户内容
Cache-Control: private, no-cache

# 敏感数据不缓存
Cache-Control: no-store

2. Connection

作用:控制当前事务完成后,是否关闭网络连接。

详细说明:

  • keep-alive:保持连接打开,允许在同一连接上发送多个请求
  • close:本次响应后关闭连接
  • 自定义值:可以传递自定义的头部,如Connection: X-My-Custom-Header

工作机制

  1. HTTP/1.0 默认关闭连接,需要显式指定keep-alive
  2. HTTP/1.1 默认保持连接,需要关闭时才指定close

相关头部

  • Keep-Alive:指定keep-alive行为的参数

    复制代码
    Keep-Alive: timeout=5, max=1000
    # timeout: 保持空闲连接的时间(秒)
    # max: 该连接上最多可发送的请求数

应用示例

http 复制代码
# 客户端请求保持连接
GET / HTTP/1.1
Connection: keep-alive

# 服务器响应保持连接
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100

3. Date

作用:消息生成的日期和时间,使用固定的GMT格式。

详细说明:

复制代码
Date: Tue, 15 Aug 2023 10:30:00 GMT

格式要求

  • 必须使用格林威治标准时间(GMT)
  • 必须使用RFC 7231定义的固定格式
  • 星期和月份必须使用英文缩写

有效格式

复制代码
Date: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT

示例

复制代码
Date: Mon, 14 Aug 2023 14:30:00 GMT
Date: Wed, 21 Oct 2015 07:28:00 GMT

重要用途

  1. 计算缓存新鲜度 :与Cache-Controlmax-age结合使用
  2. 调试和日志:帮助排查时间相关问题
  3. 条件请求 :作为If-Modified-Since的参考时间

注意事项

  • 服务器时钟必须准确同步
  • 如果响应包含Age头部,缓存时间应从Date计算
  • 代理服务器不应修改Date头部

4. Pragma

作用:HTTP/1.0的遗留头部,用于向后兼容。

详细说明:

复制代码
Pragma: no-cache

历史背景

  • HTTP/1.0时代没有Cache-Control头部
  • Pragma用于控制缓存行为
  • HTTP/1.1引入Cache-Control后逐渐废弃

唯一有效值

  • no-cache:与Cache-Control: no-cache效果相同

当前用法

http 复制代码
# 为了向后兼容,通常两者一起使用
Cache-Control: no-cache
Pragma: no-cache

特殊情况

  • 某些旧代理服务器可能只识别Pragma
  • 某些API要求同时发送两个头部确保兼容性

5. Transfer-Encoding

作用:指定传输消息体时使用的编码方式。

详细说明:

主要值:
  1. chunked(分块传输):

    • 在不知道内容长度时使用
    • 将数据分成一系列分块发送
    • 每个分块包含:长度(十六进制) + CRLF + 数据 + CRLF
    • 以长度为0的分块结束

    示例

    http 复制代码
    HTTP/1.1 200 OK
    Transfer-Encoding: chunked
    
    4\r\n
    Wiki\r\n
    5\r\n
    pedia\r\n
    0\r\n
    \r\n
  2. gzip, deflate, br

    • 表示内容已被压缩
    • 通常与Content-Encoding配合使用
    • 注意:Transfer-Encoding关注传输过程,Content-Encoding关注内容格式
  3. compress(已废弃):

    • 使用LZW算法压缩
    • 现代浏览器已不支持
重要特性:
  • 可以指定多个值,按顺序应用:

    复制代码
    Transfer-Encoding: gzip, chunked
    # 先gzip压缩,再分块传输
  • Content-Length互斥:

    • 如果指定了Transfer-Encoding: chunked,则不能有Content-Length
    • 两者同时存在时,Transfer-Encoding优先
使用场景:
  1. 动态内容:服务器生成内容时不知道最终大小
  2. 流式传输:实时推送数据(如服务器推送事件)
  3. 大文件上传:客户端上传未知大小的文件

6. Upgrade

作用:请求将连接升级到其他协议。

详细说明:

升级HTTP到WebSocket:
http 复制代码
# 客户端请求升级
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

# 服务器同意升级
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
升级到HTTP/2:
http 复制代码
# 客户端请求HTTP/2
GET / HTTP/1.1
Host: example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

# 服务器响应
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
支持的协议:
  • websocket
  • h2(HTTP/2 over TLS)
  • h2c(HTTP/2 over cleartext TCP)
  • IRC/6.9
  • RTA/x11
注意事项:
  1. 101状态码:升级成功返回101 Switching Protocols
  2. Connection头必须 :必须同时包含Connection: Upgrade
  3. 服务器选择权:服务器可以拒绝升级,继续使用当前协议
  4. TLS连接:HTTPS连接的升级有特殊规则

7. Via

作用:追踪消息经过的代理服务器路径。

详细说明:

格式:
复制代码
Via: 1.1 proxy1, 1.1 proxy2, 1.0 proxy3

每个代理添加自己的信息:

复制代码
协议版本 主机名 [注释]
示例:
http 复制代码
# 请求经过多个代理
GET / HTTP/1.1
Host: example.com
Via: 1.1 proxy1.internal.net, 1.0 proxy2.external.com

# 每个代理追加自己的信息
# 最终头部可能变成:
Via: 1.1 client, 1.1 proxy1, 1.0 proxy2, 1.1 proxy3
版本标识:
  • 1.0:HTTP/1.0
  • 1.1:HTTP/1.1
  • 2.0:HTTP/2
  • 3.0:HTTP/3
注释内容:

代理服务器可以添加额外信息:

复制代码
Via: 1.1 proxy1 (Cache-Miss)
Via: 1.0 proxy2 (Compressed)
重要用途:
  1. 调试:追踪请求路径,排查网络问题
  2. 防止循环:代理服务器检查是否已经处理过该请求
  3. 统计:分析网络拓扑和流量路径
  4. 安全:识别请求是否经过不可信代理
相关头部:
  • Forwarded:更现代的替代方案,包含更详细的信息
  • X-Forwarded-For:非标准但广泛使用的客户端IP记录

8. Warning

作用:携带关于消息状态或转换的额外警告信息(已废弃)。

详细说明:

格式:
复制代码
Warning: 110 proxy "Response is stale"

结构:警告码 警告代理 "警告文本" [日期]

标准警告码:
  • 110:Response is stale - 响应已过期
  • 111:Revalidation failed - 重新验证失败
  • 112:Disconnected operation - 断开连接操作
  • 113:Heuristic expiration - 启发式过期
  • 199:Miscellaneous warning - 杂项警告
  • 214:Transformation applied - 已应用转换
  • 299:Miscellaneous persistent warning - 持久性杂项警告
示例:
http 复制代码
HTTP/1.1 200 OK
Warning: 110 proxy "Response is stale"
Warning: 111 cache "Revalidation failed"
Warning: 214 proxy "Transformation applied"
Date: Tue, 15 Aug 2023 10:30:00 GMT
Cache-Control: max-age=3600
废弃原因:
  1. 复杂性:实现和维护复杂
  2. 混淆:容易与HTTP状态码混淆
  3. 替代方案:现代缓存控制机制更完善
  4. 有限使用:实际使用场景有限
现代替代方案:
  • 使用特定的状态码
  • 在响应体中包含错误信息
  • 使用自定义头部

二、请求头部

1. Host

作用:指定请求的目标服务器域名和端口号(HTTP/1.1必需)。

详细说明:

基本格式:
复制代码
Host: www.example.com:443

复制代码
Host: api.example.com
主要用途:
  1. 虚拟主机支持:多个域名共享同一IP地址时,服务器根据Host区分
  2. 端口指定:显式指定非标准端口
  3. HTTP/1.1要求:所有HTTP/1.1请求必须包含Host头部
示例:
http 复制代码
GET /index.html HTTP/1.1
Host: www.example.com

GET /api/data HTTP/1.1
Host: api.example.com:8080
特殊情况:
  • 默认端口:HTTP默认80,HTTPS默认443,通常省略

  • IPv6地址 :需要用方括号括起来

    复制代码
    Host: [2001:db8::1]:8080
  • HTTP/1.0:可选,但推荐包含

安全注意事项:
  1. Host头注入:未验证Host头部可能导致安全漏洞
  2. 相对路径解析:代理服务器需要正确解析Host
  3. 重定向:重定向时可能需要保留原始Host

2. User-Agent

作用:标识发起请求的客户端软件信息。

详细说明:

标准格式:
复制代码
User-Agent: Mozilla/5.0 (平台信息) 引擎信息 浏览器信息 扩展信息
组成部分:
  1. 产品标识符:主要软件名称和版本
  2. 注释:括号内的详细系统信息
  3. 可选扩展:其他相关信息
常见示例:

Chrome on Windows:

复制代码
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36

Firefox on macOS:

复制代码
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0

Mobile Chrome:

复制代码
Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36

cURL:

复制代码
curl/7.77.0
主要用途:
  1. 统计分析:了解用户设备分布
  2. 功能适配:根据客户端能力返回不同内容
  3. 反爬虫:识别自动化请求
  4. 调试:客户端问题诊断
服务器端处理:
javascript 复制代码
// 常见的User-Agent检测
const ua = req.headers['user-agent'];

if (ua.includes('Mobile')) {
  // 返回移动端页面
} else if (ua.includes('bot')) {
  // 处理爬虫
} else if (ua.includes('curl')) {
  // 命令行请求
}
注意事项:
  1. 易伪造:User-Agent可以被轻易修改
  2. 隐私问题:可能泄露过多用户信息
  3. 复杂性:字符串格式混乱,解析困难
  4. 标准化:WHATWG正在制定Client Hints作为替代方案

3. Accept

作用:告诉服务器客户端能够处理的MIME类型及其优先级。

详细说明:

基本语法:
复制代码
Accept: 类型/子类型; q=权重
  • 多个类型用逗号分隔
  • q值范围0.000-1.000,默认1.000
  • 星号(*)表示通配符
常见示例:
复制代码
# 优先HTML,其次是XML,最后是任意类型
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8

# JSON优先,XML其次
Accept: application/json, application/xml;q=0.9

# 图片格式偏好
Accept: image/webp, image/apng, image/*;q=0.8
详细示例:
http 复制代码
GET /data HTTP/1.1
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
Accept-Charset: utf-8, iso-8859-1;q=0.5
Accept-Encoding: gzip, deflate
Accept-Language: en-US, en;q=0.9, zh-CN;q=0.8, zh;q=0.7
质量值(q)规则:
复制代码
Accept: text/html, text/plain;q=0.5, text/x-dvi;q=0.8

等价于:

  • text/html → q=1.0
  • text/x-dvi → q=0.8
  • text/plain → q=0.5
特殊值:
  1. 媒体范围

    复制代码
    Accept: text/*
    Accept: image/*
    Accept: */*
  2. 参数扩展

    复制代码
    Accept: text/html;level=1;q=0.4
    Accept: text/html;q=0.7;level=1
服务器响应:

服务器根据Accept头部选择最合适的Content-Type:

http 复制代码
HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept

如果无法满足,返回406 Not Acceptable。

Vary头部配合:
复制代码
Vary: Accept

告诉缓存服务器根据Accept头部缓存不同版本。


4. Accept-Language

作用:声明客户端偏好的自然语言。

详细说明:

语法格式:
复制代码
Accept-Language: 语言标签[;q=权重]
语言标签格式:
  1. 基础语言en, zh, ja
  2. 地区变体en-US, zh-CN, zh-TW
  3. 扩展zh-Hans, zh-Hant
  4. 脚本sr-Latn(塞尔维亚语拉丁字母)
示例:
复制代码
# 英语优先,简体中文其次
Accept-Language: en-US, en;q=0.9, zh-CN;q=0.8

# 多种语言偏好
Accept-Language: zh-CN, zh;q=0.9, en-US;q=0.8, en;q=0.7, ja;q=0.6

# 简单的偏好
Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5
质量值处理:
复制代码
Accept-Language: da, en-gb;q=0.8, en;q=0.7

服务器选择顺序:da → en-gb → en

服务器响应:
  1. 内容协商:返回对应语言版本的资源
  2. 多语言网站:根据Accept-Language重定向
  3. 默认语言:没有匹配时返回默认语言
响应示例:
http 复制代码
HTTP/1.1 200 OK
Content-Language: zh-CN
Content-Type: text/html; charset=utf-8
Vary: Accept-Language
实际应用:
javascript 复制代码
// 服务器端语言检测
function detectLanguage(acceptLanguage) {
  const languages = acceptLanguage.split(',')
    .map(lang => {
      const [language, q = 'q=1'] = lang.split(';');
      const quality = parseFloat(q.split('=')[1]) || 1;
      return { language: language.trim(), quality };
    })
    .sort((a, b) => b.quality - a.quality);
  
  return languages[0]?.language || 'en';
}
注意事项:
  1. 用户设置:通常来自浏览器语言设置
  2. 缓存问题 :需要配合Vary: Accept-Language
  3. 精确匹配zh-CNzh需要分别处理
  4. 权重继承zh的权重会传递给zh-CN等子标签

5. Accept-Charset

作用:声明客户端支持的字符编码(已废弃)。

详细说明:

历史背景:
复制代码
Accept-Charset: utf-8, iso-8859-1;q=0.5
  • HTTP/1.1引入,但现代浏览器已基本不再发送
  • 被Content-Type中的charset参数替代
曾经的作用:
  1. 字符集协商:客户端告知支持的字符集
  2. 编码回退:设置备选字符集
  3. 国际化:支持多语言字符集
废弃原因:
  1. UTF-8普及:现代Web普遍使用UTF-8
  2. Content-Type优先:响应中直接指定charset
  3. 冗余:Accept头部可以包含charset参数
  4. 实现复杂:服务器处理逻辑复杂
现代替代方案:
复制代码
Content-Type: text/html; charset=utf-8

复制代码
Accept: text/html;charset=utf-8
兼容处理:

如果收到Accept-Charset,服务器可以:

  1. 忽略(现代常见做法)
  2. 解析并选择合适字符集
  3. 返回406 Not Acceptable(如果完全不支持)

6. Accept-Encoding

作用:声明客户端支持的内容编码(通常是压缩算法)。

详细说明:

语法:
复制代码
Accept-Encoding: 编码1, 编码2;q=权重
常用编码:
  1. gzip:使用LZ77算法,广泛支持
  2. deflate:使用zlib格式
  3. br:Brotli算法,压缩率更高
  4. compress:UNIX compress程序格式(已废弃)
  5. identity:不压缩
  6. *:任意编码(不建议)
示例:
复制代码
# 常见现代浏览器
Accept-Encoding: gzip, deflate, br

# 优先Brotli,其次是gzip
Accept-Encoding: br;q=1.0, gzip;q=0.8, deflate;q=0.6, *;q=0.1

# 不接收压缩
Accept-Encoding: identity
质量值示例:
复制代码
Accept-Encoding: br;q=1.0, gzip;q=0.8, deflate;q=0.6

选择顺序:br → gzip → deflate

服务器响应:
http 复制代码
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
特殊情况:
  1. 无匹配编码:返回406 Not Acceptable或使用identity
  2. 代理处理:代理不应重新压缩已压缩内容
  3. 分块传输:压缩后再分块传输
实际配置:
nginx 复制代码
# Nginx配置示例
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_vary on;
gzip_min_length 1000;
注意事项:
  1. CPU开销:压缩需要服务器CPU资源
  2. 小文件:太小的文件压缩可能适得其反
  3. 动态内容:每次请求都需要重新压缩
  4. 缓存 :需要配合Vary: Accept-Encoding

7. Authorization

作用:向服务器提供身份验证凭据。

详细说明:

基本语法:
复制代码
Authorization: 认证方案 凭据
主要认证方案:
1. Basic认证:
复制代码
Authorization: Basic base64(username:password)

示例

复制代码
Authorization: Basic dXNlcjpwYXNzd29yZA==
# base64解码:user:password

特点

  • 明文传输(base64不是加密)
  • 适合HTTPS环境
  • 简单但安全性低
2. Bearer认证(令牌):
复制代码
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

示例

复制代码
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

用途

  • OAuth 2.0访问令牌
  • JWT令牌
  • API密钥
3. Digest认证:
复制代码
Authorization: Digest username="Mufasa",
  realm="testrealm@host.com",
  nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
  uri="/dir/index.html",
  response="6629fae49393a05397450978507c4ef1",
  opaque="5ccc069c403ebaf9f0171e9517f40e41"

特点

  • 挑战-响应机制
  • 密码不直接传输
  • 比Basic安全,但复杂
4. AWS签名:
复制代码
Authorization: AWS4-HMAC-SHA256
  Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,
  SignedHeaders=host;range;x-amz-date,
  Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
自定义方案:
复制代码
Authorization: Custom token123456789
服务器响应:
  1. 验证成功:正常处理请求

  2. 验证失败 :401 Unauthorized

    http 复制代码
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: Basic realm="Access to the staging site"
  3. 过期/无效:可能返回403 Forbidden

WWW-Authenticate头部:

服务器要求认证时返回:

复制代码
WWW-Authenticate: Bearer realm="example", 
  error="invalid_token",
  error_description="The access token expired"
安全最佳实践:
  1. HTTPS:始终在TLS上使用认证
  2. 令牌过期:设置合理的令牌有效期
  3. 刷新机制:使用refresh token更新访问令牌
  4. 范围限制:令牌应有最小必要权限
  5. 安全存储:客户端安全存储凭据

作用:存储客户端状态信息,每次请求自动发送给服务器。

详细说明:

基本格式:
复制代码
Cookie: name=value[; name2=value2...]
完整示例:
复制代码
Cookie: sessionId=abc123; userId=user456; theme=dark; lang=en-US
Cookie属性(在Set-Cookie响应中设置,请求中只发送名称值对):
  1. Expires/Max-Age:过期时间
  2. Domain:生效域名
  3. Path:生效路径
  4. Secure:仅HTTPS传输
  5. HttpOnly:禁止JavaScript访问
  6. SameSite:跨站请求控制
SameSite属性详解:
复制代码
Set-Cookie: sessionId=abc123; SameSite=Lax
  • Strict:严格模式,完全禁止跨站发送
  • Lax:宽松模式,允许GET导航请求
  • None:允许跨站,但必须设置Secure
服务器端设置示例:
http 复制代码
HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
Set-Cookie: userPrefs=darkMode; Path=/; Max-Age=86400
Cookie大小限制:
  • RFC规范:至少4096字节
  • 实际实现:不同浏览器限制不同
  • 数量限制:每个域名通常50-150个
现代替代方案:
  1. HTTP状态令牌:无状态认证
  2. IndexedDB:客户端大量数据存储
  3. LocalStorage:简单键值存储
安全最佳实践:
javascript 复制代码
// 安全的Cookie设置
res.setHeader('Set-Cookie', [
  `sessionId=${token}; HttpOnly; Secure; SameSite=Strict; Path=/`,
  `csrfToken=${csrf}; Secure; SameSite=Strict; Path=/`
]);

9. Referer(注意拼写错误,应为Referrer)

作用:指示当前请求的来源页面URL。

详细说明:

基本格式:
复制代码
Referer: <完整或部分URL>
示例:
复制代码
Referer: https://www.google.com/search?q=http+headers
Referer: https://example.com/page1.html
Referer: // 无协议的相对URL(少见)
发送规则:
  1. 页面导航:点击链接、表单提交时发送
  2. 资源加载:图片、脚本、样式等子资源通常发送
  3. 同源策略:通常发送完整URL
  4. 跨源策略:可能被Referrer-Policy限制
不发送Referer的情况:
  1. 直接输入地址:地址栏直接输入
  2. 书签访问:从书签打开
  3. 隐私模式:某些隐私浏览模式
  4. HTTPS→HTTP:安全降级时不发送(默认)
  5. 页面重定向:某些重定向可能不发送
Referrer-Policy策略:
复制代码
Referrer-Policy: no-referrer-when-downgrade

策略值

  • no-referrer:从不发送
  • no-referrer-when-downgrade:HTTPS→HTTP时不发送(默认)
  • origin:只发送源(协议+主机+端口)
  • origin-when-cross-origin:跨源时发送源,同源时发送完整
  • same-origin:同源时发送完整,跨源时不发送
  • strict-origin:只发送源,且HTTPS→HTTP时不发送
  • strict-origin-when-cross-origin:跨源时发送源,同源时发送完整,且HTTPS→HTTP时不发送
  • unsafe-url:总是发送完整URL(不安全)
安全考虑:
  1. 信息泄露 :可能泄露敏感查询参数

    复制代码
    Referer: https://example.com/reset-password?token=abc123
  2. 隐私保护:需要适当限制Referer信息

  3. 防盗链:基于Referer的资源保护

防盗链实现:
nginx 复制代码
location /images/ {
    # 只允许本域和信任域名引用
    valid_referers none blocked example.com *.example.com google.com;
    
    if ($invalid_referer) {
        return 403;
    }
}

10. Origin

作用:指示请求的来源(协议+域名+端口),用于CORS机制。

详细说明:

基本格式:
复制代码
Origin: <协议>://<主机>[:端口]
示例:
复制代码
Origin: https://www.example.com
Origin: http://localhost:3000
Origin: null  # 文件协议或无来源
Origin: file://  # 本地文件
发送条件:
  1. 跨域请求:所有跨域请求
  2. 同源请求:POST、PATCH、DELETE方法
  3. 排除情况:简单GET、HEAD通常不发送
CORS流程示例:
http 复制代码
# 简单请求(自动发送Origin)
GET /api/data HTTP/1.1
Host: api.example.com
Origin: https://www.example.com

# 服务器响应
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
http 复制代码
# 预检请求(复杂请求先发送OPTIONS)
OPTIONS /api/data HTTP/1.1
Host: api.example.com
Origin: https://www.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header

# 服务器预检响应
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-Custom-Header
特殊值处理:
  1. null来源
    • file:// 协议
    • 沙盒化iframe
    • 数据URL
  2. 不透明源:某些隐私上下文
  3. 源继承:iframe内嵌页面继承父页面源
与Referer的区别:
特性 Origin Referer
内容 仅协议+主机+端口 完整URL
用途 CORS安全机制 来源追踪
隐私 信息较少 信息较多
控制 不能完全禁用 可通过策略控制
服务器验证:
javascript 复制代码
// Express.js CORS验证
app.use((req, res, next) => {
  const allowedOrigins = ['https://example.com', 'https://admin.example.com'];
  const origin = req.headers.origin;
  
  if (allowedOrigins.includes(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
    res.setHeader('Access-Control-Allow-Credentials', 'true');
  }
  
  // 预检请求处理
  if (req.method === 'OPTIONS') {
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    res.setHeader('Access-Control-Max-Age', '86400');
    return res.sendStatus(204);
  }
  
  next();
});

11. If-None-Match

作用:条件请求,基于ETag验证资源是否变化。

详细说明:

基本格式:
复制代码
If-None-Match: "etag-value"
If-None-Match: "etag1", "etag2", ...
If-None-Match: *  # 任何ETag
工作原理:
  1. 客户端首次获取资源,服务器返回ETag
  2. 客户端缓存资源并记录ETag
  3. 后续请求时发送If-None-Match
  4. 服务器比较ETag,决定返回304或200
完整流程:
http 复制代码
# 第一次请求
GET /api/data HTTP/1.1

HTTP/1.1 200 OK
ETag: "abc123"
Content-Type: application/json
Cache-Control: max-age=3600

{"data": "value"}

# 第二次请求(带ETag验证)
GET /api/data HTTP/1.1
If-None-Match: "abc123"

# 资源未修改
HTTP/1.1 304 Not Modified
ETag: "abc123"

# 资源已修改
HTTP/1.1 200 OK
ETag: "def456"
Content-Type: application/json

{"data": "updated value"}
ETag类型:
  1. 强验证器 :内容完全匹配

    复制代码
    ETag: "abc123"
  2. 弱验证器 :语义相同即可(加W/前缀)

    复制代码
    ETag: W/"abc123"  # 弱ETag
    If-None-Match: W/"abc123"
特殊值"*":
  • 用于PUT操作检查资源是否存在
  • 对于GET,匹配任何现有资源
与If-Modified-Since结合:
http 复制代码
GET /resource HTTP/1.1
If-None-Match: "abc123"
If-Modified-Since: Tue, 15 Aug 2023 10:30:00 GMT

服务器优先使用ETag验证。

实现示例:
javascript 复制代码
// Express.js ETag验证
app.get('/api/data', (req, res) => {
  const data = getDataFromDatabase();
  const etag = generateETag(data);
  
  // 检查If-None-Match
  const clientETag = req.headers['if-none-match'];
  if (clientETag && clientETag === etag) {
    return res.status(304).end();
  }
  
  res.setHeader('ETag', etag);
  res.json(data);
});

function generateETag(data) {
  // 简单实现:使用内容的哈希
  const hash = require('crypto')
    .createHash('md5')
    .update(JSON.stringify(data))
    .digest('hex');
  return `"${hash}"`;
}

12. If-Modified-Since

作用:基于时间戳的条件请求。

详细说明:

基本格式:
复制代码
If-Modified-Since: <HTTP日期>
完整示例:
http 复制代码
GET /article.html HTTP/1.1
If-Modified-Since: Tue, 15 Aug 2023 10:30:00 GMT
工作原理:
  1. 服务器响应包含Last-Modified
  2. 客户端缓存并记录时间
  3. 后续请求发送If-Modified-Since
  4. 服务器比较时间决定是否返回新内容
服务器响应逻辑:
javascript 复制代码
function handleConditionalRequest(req, res, filePath) {
  const stats = fs.statSync(filePath);
  const lastModified = stats.mtime.toUTCString();
  const clientModified = req.headers['if-modified-since'];
  
  if (clientModified) {
    const clientDate = new Date(clientModified);
    const serverDate = new Date(lastModified);
    
    // 注意:服务器时间 <= 客户端时间,表示未修改
    if (serverDate <= clientDate) {
      res.writeHead(304, {
        'Last-Modified': lastModified,
        'Cache-Control': 'public, max-age=3600'
      });
      return res.end();
    }
  }
  
  // 返回新内容
  res.writeHead(200, {
    'Last-Modified': lastModified,
    'Content-Type': 'text/html'
  });
  res.end(content);
}
精度问题:
  • 秒级精度:HTTP日期只精确到秒
  • 1秒内修改:无法检测
  • 时钟漂移:依赖服务器时钟准确
常见场景:
  1. 静态文件:适合修改不频繁的文件
  2. 动态内容:需要精确控制Last-Modified
  3. CDN缓存:配合Cache-Control使用
与ETag对比:
方面 If-Modified-Since If-None-Match
依据 修改时间 内容哈希
精度 秒级 字节级
时钟 依赖时钟同步 无依赖
开销 较小 需要计算哈希
适用 静态文件 动态内容
最佳实践:
nginx 复制代码
# Nginx配置
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    add_header Last-Modified "";
    # 禁用Last-Modified,强制使用ETag
}

13. If-Match

作用:乐观锁机制,确保资源未被修改。

详细说明:

基本格式:
复制代码
If-Match: "etag-value"
If-Match: "etag1", "etag2", ...
If-Match: *  # 任何ETag都匹配
使用场景:
  1. 资源更新:防止覆盖他人修改
  2. 删除操作:确保删除的是正确版本
  3. 并发控制:实现乐观锁
完整示例:
http 复制代码
# 1. 获取资源
GET /article/123 HTTP/1.1

HTTP/1.1 200 OK
ETag: "version1"
Content-Type: application/json

{"id": 123, "title": "Original", "version": 1}

# 2. 更新资源(携带ETag)
PUT /article/123 HTTP/1.1
If-Match: "version1"
Content-Type: application/json

{"id": 123, "title": "Updated", "version": 2}

# 3a. ETag匹配,更新成功
HTTP/1.1 200 OK
ETag: "version2"

# 3b. ETag不匹配,其他人已修改
HTTP/1.1 412 Precondition Failed
特殊值"*"的意义:
复制代码
If-Match: *
  • 对于更新:资源必须存在
  • 对于删除:无条件删除(危险)
  • 避免使用:可能导致数据丢失
服务器实现:
javascript 复制代码
// REST API的乐观锁实现
app.put('/resources/:id', async (req, res) => {
  const resourceId = req.params.id;
  const clientETag = req.headers['if-match'];
  const newData = req.body;
  
  // 获取当前资源
  const currentResource = await db.get(resourceId);
  const currentETag = generateETag(currentResource);
  
  // 验证ETag
  if (!clientETag) {
    return res.status(428).json({ error: 'Precondition required' });
  }
  
  if (clientETag !== '*' && clientETag !== currentETag) {
    return res.status(412).json({ 
      error: 'Precondition failed',
      currentETag: currentETag
    });
  }
  
  // 更新资源
  const updatedResource = await db.update(resourceId, newData);
  const newETag = generateETag(updatedResource);
  
  res.setHeader('ETag', newETag);
  res.json(updatedResource);
});
结合版本号:
json 复制代码
{
  "id": 123,
  "title": "Article",
  "content": "...",
  "version": 5,
  "updatedAt": "2023-08-15T10:30:00Z"
}
http 复制代码
PUT /articles/123 HTTP/1.1
If-Match: "v5"
Content-Type: application/json

{"title": "New Title", "version": 5}
错误处理:
  1. 412 Precondition Failed:ETag不匹配
  2. 428 Precondition Required:需要If-Match头部
  3. 400 Bad Request:ETag格式错误

14. Range

作用:请求资源的特定部分,实现断点续传和流式传输。

详细说明:

基本格式:
复制代码
Range: bytes=<start>-<end>
Range: bytes=<start>-
Range: bytes=-<suffix-length>
Range: bytes=<range1>, <range2>, ...
示例:
复制代码
Range: bytes=0-499          # 前500字节
Range: bytes=500-999        # 第二个500字节
Range: bytes=500-           # 从500字节到末尾
Range: bytes=-500           # 最后500字节
Range: bytes=0-499,1000-1499  # 多个范围(少见)
服务器响应:

单范围成功

http 复制代码
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-499/12345
Content-Length: 500
Content-Type: application/octet-stream

[数据]

多范围成功

http 复制代码
HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=boundary_string

--boundary_string
Content-Type: application/octet-stream
Content-Range: bytes 0-499/12345

[第一部分数据]
--boundary_string
Content-Type: application/octet-stream
Content-Range: bytes 1000-1499/12345

[第二部分数据]
--boundary_string--

不支持范围请求

http 复制代码
HTTP/1.1 200 OK
Content-Length: 12345
Content-Type: application/octet-stream

[完整数据]
断点续传实现:
javascript 复制代码
// Express.js 范围请求处理
const fs = require('fs');
const path = require('path');

app.get('/download/:filename', (req, res) => {
  const filePath = path.join(__dirname, 'files', req.params.filename);
  const stat = fs.statSync(filePath);
  const fileSize = stat.size;
  
  // 解析Range头部
  const range = req.headers.range;
  
  if (range) {
    const parts = range.replace(/bytes=/, "").split("-");
    const start = parseInt(parts[0], 10);
    const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
    const chunkSize = (end - start) + 1;
    
    const file = fs.createReadStream(filePath, { start, end });
    
    res.writeHead(206, {
      'Content-Range': `bytes ${start}-${end}/${fileSize}`,
      'Accept-Ranges': 'bytes',
      'Content-Length': chunkSize,
      'Content-Type': 'application/octet-stream'
    });
    
    file.pipe(res);
  } else {
    // 完整文件
    res.writeHead(200, {
      'Content-Length': fileSize,
      'Content-Type': 'application/octet-stream'
    });
    
    fs.createReadStream(filePath).pipe(res);
  }
});
相关头部:

Accept-Ranges

http 复制代码
Accept-Ranges: bytes
Accept-Ranges: none

Content-Range

复制代码
Content-Range: bytes <start>-<end>/<total>
Content-Range: bytes */<total>  # 无效范围时

If-Range

复制代码
If-Range: "etag-value"
If-Range: <HTTP-date>
  • 如果条件满足,返回范围内容
  • 如果条件不满足,返回完整内容
应用场景:
  1. 大文件下载:分段下载,断点续传
  2. 视频播放:随机访问,跳转播放
  3. 图片懒加载:渐进式加载
  4. HTTP流:实时数据传输
注意事项:
  1. 字节对齐:某些编码可能需要对齐
  2. 缓存问题:部分响应需要特殊缓存处理
  3. 代理支持:确保代理正确处理206状态码
  4. 多范围限制:实现复杂,支持有限
相关推荐
灰子学技术10 小时前
Envoy HTTP 过滤器处理技术文档
网络·网络协议·http
时空自由民.14 小时前
HTTP协议和HTTPS协议结合天气获取案例介绍
网络协议·http·https
时空自由民.20 小时前
HTTP协议帧格式
网络·网络协议·http
Rust研习社1 天前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
灰子学技术1 天前
Envoy HTTP 流量层面的 Metric 指标分析
网络·网络协议·http
TimeAground1 天前
HTTP 协议全解:从报文到 HTTP/3,Android 开发者需要知道的一切
http
lifewange1 天前
如何设计一个 RESTful API
后端·http·restful
夜瞬2 天前
HTTP基础教程:请求方法、状态码、JSON、鉴权、超时、重试与流式返回
网络协议·http·json