深入理解HTTP头部字段的作用、格式及实际应用
Header(头部)是HTTP消息的元数据(Metadata)
| 特性 | Header | Body |
|---|---|---|
| 内容 | 元数据(描述信息) | 实际数据 |
| 格式 | 键值对(key: value) | 任意格式 |
| 位置 | 请求/响应的开头部分 | Header之后 |
| 编码 | 通常为ASCII | 可能是二进制 |
Host: www.example.com
两个核心功能:
同一台物理服务器运行:
Host Header告诉服务器:我要访问哪个服务
告诉接收方Body中的数据是什么格式
Content-Type: text/html; charset=utf-8
Content-Type: application/x-www-form-urlencoded
first_name=John&last_name=Doe&age=25
Android Retrofit示例:
@FormUrlEncoded
@POST("users")
Call<User> createUser(
@Field("first_name") String firstName,
@Field("last_name") String lastName,
@Field("age") int age
);
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="username"
JohnDoe
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="avatar"; filename="photo.jpg"
Content-Type: image/jpeg
[二进制文件数据]
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Android Retrofit示例:
@Multipart
@POST("users/{id}/avatar")
Call<User> updateAvatar(
@Path("id") String id,
@Part MultipartBody.Part avatar
);
// 创建文件Part
File file = new File("photo.jpg");
RequestBody requestFile = RequestBody.create(
MediaType.parse("image/jpeg"),
file
);
MultipartBody.Part avatarPart = MultipartBody.Part.createFormData(
"avatar",
file.getName(),
requestFile
);
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"age": 25
}
Android Retrofit配置:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create()) // JSON转换器
.build();
Content-Type: image/jpeg // JPEG图片
Content-Type: application/zip // ZIP压缩包
Content-Type: application/pdf // PDF文档
Android Retrofit示例:
@POST("users/{id}/avatar")
Call<User> updateAvatar(
@Path("id") String id,
@Body RequestBody avatar
);
// 创建RequestBody
File avatarFile = new File("avatar.jpg");
RequestBody avatarBody = RequestBody.create(
MediaType.parse("image/jpeg"),
avatarFile
);
Content-Length: 1024
POST /upload HTTP/1.1
Host: example.com
Content-Type: text/plain
Content-Length: 13
Hello World!
当Body长度无法预先确定时使用
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/plain
7\r\n ← 块长度(7字节,十六进制)
Hello W\r\n ← 块数据
6\r\n ← 下一个块长度
orld!\r\n ← 块数据
0\r\n ← 结束标志(长度为0)
\r\n ← 结束后的空行
POST /stream HTTP/1.1
Host: example.com
Transfer-Encoding: chunked
Content-Type: application/json
1A\r\n
{"status":"processing"}\r\n
1F\r\n
{"status":"completed","result":123}\r\n
0\r\n
\r\n
服务器告诉客户端资源的新位置
HTTP/1.1 302 Found
Location: https://new-location.com/resource
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/120.0.0.0 Safari/537.36
// 客户端请求部分内容
GET /large-file.zip HTTP/1.1
Range: bytes=0-1023
// 服务器响应部分内容
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/1048576
Content-Length: 1024
线程1: Range: bytes=0-1048575
线程2: Range: bytes=1048576-2097151
线程3: Range: bytes=2097152-3145727
Accept-Ranges: bytes // 服务器支持范围请求
Accept-Ranges: none // 服务器不支持范围请求
GET /profile HTTP/1.1
Cookie: session_id=abc123; user_prefs=dark_mode
HTTP/1.1 200 OK
Set-Cookie: session_id=xyz789; Path=/; HttpOnly; Secure; SameSite=Strict
Set-Cookie: theme=light; Max-Age=3600; Path=/
| 属性 | 说明 |
|---|---|
| Path | Cookie生效的路径 |
| Domain | Cookie生效的域名 |
| Max-Age | 过期时间(秒) |
| Expires | 过期时间(日期) |
| Secure | 仅HTTPS传输 |
| HttpOnly | 禁止JavaScript访问 |
| SameSite | 防止CSRF攻击 |
Authorization: Basic dXNlcjpwYXNzd29yZA==
// Base64编码的 username:password
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Authorization: Bearer ACCESS_TOKEN
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
q参数表示优先级(0-1)
Accept-Charset: utf-8, iso-8859-1;q=0.5
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
服务器压缩响应:
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: text/html
[gzip压缩后的HTML内容]
| 特性 | Cache(缓存) | Buffer(缓冲) |
|---|---|---|
| 目的 | 加速访问,避免重复请求 | 平衡生产消费速度 |
| 数据 | 已使用过的数据 | 待处理的数据 |
| 场景 | 网页、图片、API响应 | 视频播放、文件传输 |
| 策略 | 过期时间、验证机制 | 先进先出、大小限制 |
// 客户端发送验证请求
GET /resource HTTP/1.1
If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT
If-None-Match: "abc123"
// 服务器响应
HTTP/1.1 304 Not Modified // 资源未修改,使用缓存
// 或
HTTP/1.1 200 OK // 资源已修改,返回新内容
Cache-Control: no-cache // 强制验证
Cache-Control: no-store // 不缓存
Cache-Control: max-age=3600 // 最大缓存时间
Cache-Control: public // 可被任何缓存存储
Cache-Control: private // 仅用户私有缓存
Cache-Control: max-age=86400 // 缓存有效期(秒)
Cache-Control: must-revalidate // 过期后必须验证
// 静态资源(图片、CSS、JS)
Cache-Control: public, max-age=31536000
// HTML页面
Cache-Control: no-cache, must-revalidate
// 敏感数据
Cache-Control: no-store, private
public interface ApiService {
@FormUrlEncoded
@POST("users/register")
Call<ResponseBody> registerUser(
@Field("username") String username,
@Field("password") String password,
@Field("email") String email
);
}
public interface ApiService {
@POST("users")
Call<User> createUser(@Body User user);
// 配置Gson转换器
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public interface ApiService {
@Multipart
@POST("users/{id}/avatar")
Call<User> uploadAvatar(
@Path("id") String userId,
@Part MultipartBody.Part avatar,
@Part("description") RequestBody description
);
}
// 使用示例
File file = new File("avatar.jpg");
RequestBody requestFile = RequestBody.create(
MediaType.parse("image/jpeg"),
file
);
MultipartBody.Part avatarPart = MultipartBody.Part.createFormData(
"avatar",
file.getName(),
requestFile
);
RequestBody desc = RequestBody.create(
MediaType.parse("text/plain"),
"Profile picture"
);
@GET("users")
Call<List<User>> getUsers(
@Query("page") int page,
@Query("limit") int limit,
@Query("sort") String sort
);
// 实际请求: GET /users?page=1&limit=20&sort=name
// 防止XSS
Content-Security-Policy: default-src 'self'
// 防止点击劫持
X-Frame-Options: DENY
// 防止MIME类型嗅探
X-Content-Type-Options: nosniff
// 启用HTTPS
Strict-Transport-Security: max-age=31536000
// 启用Gzip压缩
Accept-Encoding: gzip, deflate, br
// 使用HTTP/2
Connection: Upgrade, HTTP2-Settings
// 预连接
Link: ; rel=preload; as=style
// CORS响应头
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
| 类型 | 用途 | 示例 |
|---|---|---|
| text/html | HTML页面 | 网页 |
| application/json | JSON数据 | API响应 |
| application/xml | XML数据 | RSS |
| application/x-www-form-urlencoded | 表单数据 | 登录表单 |
| multipart/form-data | 文件上传 | 头像上传 |
| image/jpeg | JPEG图片 | 照片 |
| application/pdf | PDF文档 | 报告 |
| application/zip | ZIP压缩包 | 下载包 |
| 场景 | 状态码 | 关键Header |
|---|---|---|
| 重定向 | 301/302 | Location |
| 缓存命中 | 304 | ETag, Last-Modified |
| 认证失败 | 401 | WWW-Authenticate |
| 跨域请求 | 200 | Access-Control-* |
| 文件下载 | 200 | Content-Disposition |