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. 多范围限制:实现复杂,支持有限
相关推荐
就不掉头发4 小时前
HTTP基本知识
网络·网络协议·http
阿拉伯柠檬6 小时前
应用层协议HTTP
linux·网络·c++·网络协议·http
huangql5207 小时前
HTTP超文本传输协议:互联网的统一语言
网络·网络协议·http
_F_y8 小时前
应用层协议HTTP
网络·网络协议·http
是娇娇公主~8 小时前
HTTPS 常用密钥交换算法解析
网络协议·http·面试·https
Hi, how are you8 小时前
GyAn数字资产守护系统
python·安全·http·网络安全·信息与通信
qq_463408429 小时前
React Native跨平台技术在开源鸿蒙中使用内置的`fetch` API或者第三方库如`axHarmony`来处理网络通信HTTP请求
javascript·算法·react native·react.js·http·开源·harmonyos
talenteddriver1 天前
web: http请求(自用总结)
前端·网络协议·http
ZeroNews内网穿透1 天前
EasyNode 结合 ZeroNews,实现远程管理服务器
运维·服务器·网络协议·安全·http