第 05 章:请求头与响应头
第 05 章:请求头与响应头
HTTP 头(Headers)是 HTTP 协议的"信封"——它们携带了关于请求和响应的元数据,控制着缓存、认证、内容协商、压缩等关键行为。
5.1 请求头基础
设置请求头
# 设置单个请求头
curl -H "Accept: application/json" https://api.example.com/data
# 设置多个请求头
curl -H "Accept: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "X-Request-ID: 550e8400-e29b-41d4-a716-446655440000" \
-H "X-Forwarded-For: 203.0.113.50" \
https://api.example.com/data
# 移除默认请求头(使用空值)
curl -H "Accept:" -H "User-Agent:" https://example.com
# 设置带空格的头部值
curl -H "X-Custom: hello world" https://example.com
# 设置带冒号的头部值
curl -H "Authorization: Basic dXNlcjpwYXNz" https://example.com
常用请求头速查
| 请求头 | 用途 | curl 设置方式 |
|---|---|---|
Accept | 指定期望的响应格式 | -H "Accept: application/json" |
Accept-Language | 语言偏好 | -H "Accept-Language: zh-CN,en;q=0.9" |
Accept-Encoding | 支持的压缩算法 | --compressed(自动设置) |
Authorization | 认证凭据 | -H "Authorization: Bearer token" |
Content-Type | 请求体格式 | -H "Content-Type: application/json" |
Cookie | 发送 Cookie | -b "name=value" |
User-Agent | 客户端标识 | -A "MyApp/1.0" |
Referer | 来源页面 | -e "https://example.com" |
Origin | 请求源(CORS) | -H "Origin: https://myapp.com" |
Cache-Control | 缓存策略 | -H "Cache-Control: no-cache" |
If-None-Match | 条件请求(ETag) | -H 'If-None-Match: "abc123"' |
If-Modified-Since | 条件请求(时间) | -H "If-Modified-Since: Sat, 01 Jan 2025 00:00:00 GMT" |
Range | 请求部分内容 | -H "Range: bytes=0-999" |
Host | 目标主机 | -H "Host: virtual.example.com" |
X-Forwarded-For | 客户端真实 IP | -H "X-Forwarded-For: 203.0.113.50" |
5.2 响应头解析
查看响应头
# 仅显示响应头
curl -I https://example.com
# 输出示例:
# HTTP/2 200
# content-type: text/html; charset=UTF-8
# content-length: 1256
# date: Sat, 10 May 2026 12:00:00 GMT
# server: nginx/1.24.0
# cache-control: max-age=3600
# etag: "67890-abc"
# strict-transport-security: max-age=31536000
# 显示响应头 + 响应体
curl -i https://example.com
# 提取特定响应头
curl -sI https://example.com | grep -i "content-type"
# 仅获取状态码
curl -s -o /dev/null -w "%{http_code}" https://example.com
# 获取完整的头信息(详细模式)
curl -v https://example.com 2>&1 | grep "^[<>]"
常见响应头说明
| 响应头 | 说明 | 示例值 |
|---|---|---|
Status / HTTP 状态行 | 请求结果 | HTTP/2 200 |
Content-Type | 响应体格式 | application/json; charset=utf-8 |
Content-Length | 响应体大小(字节) | 1256 |
Content-Encoding | 压缩算法 | gzip, br, zstd |
Cache-Control | 缓存策略 | max-age=3600, no-cache |
ETag | 资源版本标识 | "67890-abc" |
Last-Modified | 最后修改时间 | Sat, 10 May 2026 12:00:00 GMT |
Set-Cookie | 设置 Cookie | session=abc; Path=/; HttpOnly |
Location | 重定向目标 | /new-page |
X-Request-ID | 请求追踪 ID | 550e8400-... |
X-RateLimit-Remaining | 剩余请求次数 | 99 |
Strict-Transport-Security | HSTS 策略 | max-age=31536000 |
Access-Control-Allow-Origin | CORS 允许的源 | https://myapp.com |
5.3 Content-Type 详解
Content-Type 是最重要的头部之一,它告诉服务器(或客户端)如何解析请求/响应体。
常见 Content-Type
# application/json(REST API 标准)
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name": "张三"}'
# application/x-www-form-urlencoded(HTML 表单默认)
curl -X POST https://example.com/login \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=admin&password=secret"
# multipart/form-data(文件上传)
curl -X POST https://api.example.com/upload \
-F "[email protected]" \
-F "description=风景照"
# text/plain
curl -X POST https://api.example.com/log \
-H "Content-Type: text/plain" \
-d "2026-05-10 12:00:00 INFO Application started"
# application/xml(SOAP 服务)
curl -X POST https://soap.example.com/service \
-H "Content-Type: application/xml; charset=utf-8" \
-d '<?xml version="1.0"?><request><id>1</id></request>'
# application/octet-stream(二进制数据)
curl -X PUT https://storage.example.com/file.bin \
-H "Content-Type: application/octet-stream" \
--data-binary @file.bin
# application/pdf
curl -X POST https://api.example.com/documents \
-H "Content-Type: application/pdf" \
--data-binary @document.pdf
Content-Type 对照表
| 格式 | Content-Type | 使用场景 |
|---|---|---|
| JSON | application/json | REST API |
| 表单 | application/x-www-form-urlencoded | HTML 表单 |
| 文件上传 | multipart/form-data | 文件上传 |
| XML | application/xml 或 text/xml | SOAP、旧系统 |
| 纯文本 | text/plain | 日志、纯文本 |
| HTML | text/html | 网页 |
| CSV | text/csv | 数据导入/导出 |
application/pdf | 文档 | |
| 图片 | image/png, image/jpeg | 图片上传 |
| 二进制 | application/octet-stream | 通用二进制 |
| YAML | application/x-yaml | 配置文件 |
| Protocol Buffers | application/protobuf | gRPC、高效序列化 |
| MessagePack | application/msgpack | 高效序列化 |
5.4 Cookie 管理
Cookie 是维持 HTTP 会话状态的核心机制。curl 提供了完整的 Cookie 管理功能。
基本 Cookie 操作
# 发送 Cookie
curl -b "session=abc123; user=张三" https://example.com
# 发送单个 Cookie
curl -b "session=abc123" https://example.com
# 使用 Cookie 文件
curl -b cookies.txt https://example.com
# 保存服务器设置的 Cookie
curl -c cookies.txt https://example.com
# 同时读取和保存 Cookie(维持会话)
curl -b cookies.txt -c cookies.txt https://example.com/dashboard
Cookie 会话管理
# 完整的登录会话流程
# 1. 登录并保存 Cookie
curl -c cookies.txt -X POST https://example.com/login \
-d "username=admin&password=secret" \
-L # 跟随重定向
# 2. 使用 Cookie 访问需要认证的页面
curl -b cookies.txt https://example.com/dashboard
# 3. 查看保存的 Cookie
cat cookies.txt
# 输出示例:
# .example.com TRUE / FALSE 1715347200 session abc123
# .example.com TRUE / FALSE 1715347200 user admin
# 4. 登出(可能需要清空 Cookie)
rm cookies.txt
Cookie 格式(Netscape 格式)
# Netscape Cookie 文件格式
# domain flag path secure expiry name value
.example.com TRUE / TRUE 1715347200 session abc123
.example.com TRUE / FALSE 1715347200 theme dark
字段说明:
- domain:Cookie 所属域名
- flag:是否适用于所有子域(TRUE/FALSE)
- path:Cookie 适用路径
- secure:是否仅 HTTPS 传输
- expiry:过期时间(Unix 时间戳)
- name:Cookie 名称
- value:Cookie 值
5.5 Content Negotiation(内容协商)
# 指定期望的响应格式
curl -H "Accept: application/json" https://api.example.com/users
# 服务器返回 JSON
curl -H "Accept: application/xml" https://api.example.com/users
# 服务器返回 XML
# 多种格式,带优先级(q 值)
curl -H "Accept: application/json;q=0.9, application/xml;q=0.8, */*;q=0.1" \
https://api.example.com/users
# 语言协商
curl -H "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8" https://example.com
# 编码协商(自动解压)
curl --compressed https://example.com
# 设置了 Accept-Encoding: gzip, deflate, br
5.6 条件请求头
条件请求头用于缓存验证和乐观并发控制。
缓存验证
# ETag 条件请求
# 第一次请求,获取 ETag
curl -sI https://api.example.com/data/42
# 响应:ETag: "v1-abc123"
# 第二次请求,带上 ETag 验证缓存
curl -H 'If-None-Match: "v1-abc123"' https://api.example.com/data/42
# 304 Not Modified → 缓存仍有效
# Last-Modified 条件请求
# 第一次请求
curl -sI https://api.example.com/data/42
# 响应:Last-Modified: Sat, 10 May 2026 12:00:00 GMT
# 第二次请求
curl -H "If-Modified-Since: Sat, 10 May 2026 12:00:00 GMT" \
https://api.example.com/data/42
# 304 Not Modified → 缓存仍有效
乐观并发控制
# 使用 ETag 防止"丢失更新"
# 1. 获取资源和 ETag
curl -sI https://api.example.com/config
# 响应:ETag: "config-v3"
# 2. 更新时带上 If-Match,确保版本一致
curl -X PUT https://api.example.com/config \
-H 'If-Match: "config-v3"' \
-H "Content-Type: application/json" \
-d '{"key": "new_value"}'
# 成功:200 OK
# 版本冲突:412 Precondition Failed
5.7 自定义头部规范
X- 前缀(已废弃但常见)
# 旧式 X- 前缀自定义头(RFC 6648 已不推荐,但广泛使用)
curl -H "X-Request-ID: 550e8400-e29b-41d4-a716-446655440000" \
-H "X-Correlation-ID: abc-def-ghi" \
-H "X-Forwarded-For: 203.0.113.50" \
-H "X-Real-IP: 203.0.113.50" \
-H "X-Tenant-ID: tenant-42" \
https://api.example.com/data
常见自定义头命名
| 头部 | 用途 | 来源 |
|---|---|---|
X-Request-ID | 请求追踪 | 代理/网关生成 |
X-Correlation-ID | 分布式追踪关联 | 应用生成 |
X-Forwarded-For | 原始客户端 IP | 代理添加 |
X-Real-IP | 真实客户端 IP | 代理添加 |
X-Tenant-ID | 多租户标识 | 应用层 |
X-API-Key | API 密钥 | 应用层 |
X-CSRF-Token | CSRF 保护令牌 | 前端获取 |
X-Idempotency-Key | 幂等键 | 客户端生成 |
注意事项
- 头部名大小写不敏感:HTTP/2 强制小写,HTTP/1.1 大小写不敏感
- 多个同名头部:某些头部(如
Set-Cookie)可以有多个值 - 空头部值:
-H "Header:"会移除该默认头部 - 代理转发:
Host、X-Forwarded-*头部在经过代理时可能被修改 - 安全头部:不要在请求头中暴露敏感信息
# 查看 curl 默认发送的所有请求头
curl -v https://example.com 2>&1 | grep "^>"
# 输出示例:
# > GET / HTTP/2
# > Host: example.com
# > User-Agent: curl/8.5.0
# > Accept: */*
扩展阅读
- RFC 9110 — HTTP 语义:头部字段
- MDN — HTTP Headers
- OWASP — HTTP Security Headers
- Cookie 规范 (RFC 6265)
- Content Negotiation (MDN)
📖 下一章:第 06 章:认证机制 — 深入了解 Basic/Bearer/OAuth2/客户端证书/NTLM/Kerberos 等认证方式。