强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

HTTP 协议详解教程 / 第 6 章:HTTP 头部字段

第 6 章:HTTP 头部字段

头部字段是 HTTP 消息的元数据,控制着缓存、认证、内容协商、安全策略等核心机制。掌握头部字段是精通 HTTP 的必经之路。


6.1 头部字段基础

语法

Header-Name: Header-Value
  • 字段名:不区分大小写
  • 字段值:可能区分大小写
  • 可以有多值:用逗号分隔 Cache-Control: max-age=3600, public

分类

类型说明示例
通用头(General)请求和响应都可用Cache-Control, Connection, Date
请求头(Request)仅请求中使用Host, Accept, Authorization
响应头(Response)仅响应中使用Server, Set-Cookie, ETag
表示头(Representation)描述消息体Content-Type, Content-Length

6.2 请求头详解

主机与连接

Host: api.example.com:8080
Connection: keep-alive
头部说明示例
Host目标主机(HTTP/1.1 必须)Host: example.com
Connection连接管理keep-alive / close / Upgrade
Keep-Alive持久连接参数timeout=5, max=100

内容协商

Accept: application/json, text/html;q=0.9
Accept-Language: zh-CN, en-US;q=0.8
Accept-Encoding: gzip, br, deflate
Accept-Charset: utf-8
import requests

headers = {
    'Accept': 'application/json',
    'Accept-Language': 'zh-CN,en;q=0.9',
    'Accept-Encoding': 'gzip, br'
}
response = requests.get('https://api.example.com/data', headers=headers)
print(response.headers['Content-Type'])

认证与凭据

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Cookie: session=abc123; user=alice
Proxy-Authorization: Basic dXNlcjpwYXNz

条件请求

If-None-Match: "etag-value"
If-Modified-Since: Wed, 10 May 2026 10:00:00 GMT
If-Match: "etag-value"
If-Unmodified-Since: Wed, 10 May 2026 10:00:00 GMT
If-Range: "etag-value"
Range: bytes=0-1023

请求上下文

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Referer: https://example.com/previous-page
Origin: https://frontend.example.com
DNT: 1
X-Request-ID: 550e8400-e29b-41d4

6.3 响应头详解

内容相关

Content-Type: application/json; charset=utf-8
Content-Length: 256
Content-Encoding: gzip
Content-Language: zh-CN
Content-Disposition: attachment; filename="report.pdf"
Content-Range: bytes 0-1023/10240

缓存控制

Cache-Control: max-age=3600, public
ETag: "abc123"
Last-Modified: Wed, 10 May 2026 10:00:00 GMT
Expires: Thu, 11 May 2026 10:00:00 GMT
Vary: Accept, Accept-Encoding

安全策略

Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin

CORS

Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Access-Control-Expose-Headers: X-Total-Count
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
Set-Cookie: theme=dark; Path=/; Max-Age=31536000

6.4 Content-Type 详解

Content-Type 是最重要的头部之一,指示消息体的媒体类型。

语法

Content-Type: type/subtype[; parameter=value]

常见类型

类型说明示例场景
text/htmlHTML 文档网页
text/plain纯文本日志、调试
application/jsonJSONREST API
application/xmlXMLSOAP API
application/x-www-form-urlencoded表单HTML 表单
multipart/form-data多部分文件上传
application/octet-stream二进制流文件下载
application/pdfPDF 文档文档下载
image/jpegJPEG 图片图片资源
image/pngPNG 图片图片资源
application/javascriptJavaScript脚本文件
text/cssCSS 样式样式文件
application/wasmWebAssemblyWASM 模块

multipart/form-data 结构

POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="username"

alice
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="avatar"; filename="photo.jpg"
Content-Type: image/jpeg

<binary image data>
------WebKitFormBoundary7MA4YWxkTrZu0gW--
import requests

# 文件上传
with open('photo.jpg', 'rb') as f:
    response = requests.post(
        'https://api.example.com/upload',
        files={
            'avatar': ('photo.jpg', f, 'image/jpeg'),
        },
        data={
            'username': 'alice'
        }
    )

6.5 Cache-Control 详解

Cache-Control 控制缓存行为,是最复杂的头部之一。

指令列表

指令类型说明
max-age=N请求+响应缓存有效时间(秒)
s-maxage=N响应共享缓存有效时间(覆盖 max-age)
no-cache请求+响应可缓存但每次需验证
no-store请求+响应不缓存任何内容
public响应任何缓存都可存储
private响应仅浏览器可缓存
must-revalidate响应过期后必须验证
proxy-revalidate响应代理必须验证
immutable响应内容不会改变
stale-while-revalidate=N响应过期后可在后台验证
no-transform请求+响应不允许代理转换内容

常见缓存策略

# 静态资源(长期缓存,使用 hash 文件名)
Cache-Control: public, max-age=31536000, immutable

# API 响应(不缓存)
Cache-Control: no-store

# HTML 页面(协商缓存)
Cache-Control: no-cache

# 用户数据(仅浏览器缓存)
Cache-Control: private, max-age=300

# CDN + 浏览器缓存
Cache-Control: public, s-maxage=86400, max-age=3600
# Nginx 缓存配置
# 静态资源
location ~* \.(css|js|png|jpg|ico|woff2)$ {
    add_header Cache-Control "public, max-age=31536000, immutable";
}

# HTML
location / {
    add_header Cache-Control "no-cache";
}

# API
location /api/ {
    add_header Cache-Control "no-store";
}

6.6 自定义头部

命名规范

前缀说明示例
X-非标准(已废弃,但仍广泛使用)X-Request-ID
无前缀IANA 注册Authorization
Sec-安全相关(浏览器自动添加)Sec-Fetch-Mode

常用自定义头部

# 请求追踪
X-Request-ID: 550e8400-e29b-41d4
X-Correlation-ID: abc-123

# API 版本
X-API-Version: v2

# 限流信息(响应头)
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 85
X-RateLimit-Reset: 1715328000

# 分页信息(响应头)
X-Total-Count: 1500
X-Page-Count: 75

# 客户端信息
X-Forwarded-For: 203.0.113.1
X-Forwarded-Proto: https
X-Real-IP: 203.0.113.1
// Express.js 中间件:添加请求 ID
const { v4: uuidv4 } = require('uuid');

app.use((req, res, next) => {
    const requestId = req.headers['x-request-id'] || uuidv4();
    req.requestId = requestId;
    res.setHeader('X-Request-ID', requestId);
    next();
});

6.7 响应头 Vary

Vary 告诉缓存服务器哪些请求头影响响应内容。

# 响应根据 Accept-Encoding 不同而不同
Vary: Accept-Encoding

# 根据 Accept 和 Authorization 不同
Vary: Accept, Authorization
# Nginx Vary 配置
gzip_vary on;  # 添加 Vary: Accept-Encoding

📝 注意:Vary 设为 * 会导致缓存基本失效。


6.8 业务场景:完整请求头示例

浏览器 API 请求

GET /api/users?page=1 HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate, br
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Origin: https://app.example.com
Referer: https://app.example.com/users
Connection: keep-alive
Cache-Control: no-cache
X-Request-ID: abc-123-def-456
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site

服务器响应

HTTP/1.1 200 OK
Date: Wed, 10 May 2026 10:00:00 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 256
Content-Encoding: br
Cache-Control: private, max-age=0, must-revalidate
ETag: "user-list-v5"
Vary: Accept, Accept-Encoding
X-Request-ID: abc-123-def-456
X-Total-Count: 150
X-Page-Count: 8
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Expose-Headers: X-Total-Count, X-Page-Count
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff

⚠️ 注意事项

  1. Host 头必须:HTTP/1.1 强制要求,缺少会导致 400 错误
  2. 大小写不敏感:头部名不区分大小写,但值可能区分
  3. 重复头部:部分头部可以重复(Set-Cookie),大部分会被合并
  4. 代理影响:代理可能添加/修改头部(X-Forwarded-For 等)
  5. 自定义头部命名:IETF 已废弃 X- 前缀,但实际中仍广泛使用
  6. 不要依赖 User-Agent:可被伪造,不应作为安全决策依据

🔗 扩展阅读


下一章第 7 章:Cookie 机制 — Set-Cookie、属性详解、安全策略、Session 管理