HTTP 协议详解
HTTP 起源
HTTP
是由蒂姆·伯纳斯-李(TimBerners—Lee
)于1989年在欧洲核子研究组织(CERN
)所发起。
其中最著名的是 1999 年 6 月公布的 RFC 2616,定义了HTTP
协议中现今广泛使用的一个版本——HTTP 1.1
。
HTTP 是什么
全称: 超文本传输协议(HyperText Transfer Protocol
)。
概念: HTTP 是 客户端(如浏览器) 和 服务器 之间传输数据(如 HTML、图片、API 数据)的通信协议(client-server
)。
核心特点:
✅ Client-Server 模型: 浏览器(客户端)发送请求,服务器返回响应。
✅ 无状态协议: 默认不记录请求历史(依赖 Cookie/Session 管理状态)。
✅ 应用层协议: 基于 TCP(HTTP/1.1、HTTP/2)或 QUIC(HTTP/3)。
✅ 简单可扩展: 通过 Header 传递元数据,支持 RESTful API、缓存控制等。
HTTP 的基础特性
- 可扩展性
HTTP 采用「Header 机制」实现灵活扩展。只需客户端和服务端协商好 Header 语义,就能轻松添加新功能。例如:Cache-Control 控制缓存
,Content-Encoding 指定压缩方式
,自定义 X- 前缀头部
。 - 无状态与会话管理
HTTP 本身是无状态的,每个请求相互独立。为实现连续交互(如购物车),通过扩展机制引入:把 Cookies 添加到头部中,创建一个会话让每次请求都能共享相同的上下文信息,达成相同的状态。1
Cookie: session_id=abc123
- 连接机制
HTTP 依赖于面向连接的 TCP 进行消息传递,但连接并不是必须的。只需要它是可靠的,或不丢失消息的。
HTTP/1.0 默认为每一对 HTTP 请求/响应都打开一个单独的 TCP 连接。当需要连续发起多个请求时,这种模式比多个请求共享同一个 TCP 链接更低效。为此,HTTP 1.1 持久连接的概念,底层 TCP 连接可以通过 connection 头部实现。
HTTP 组件架构
- 客户端 (User Agent)
核心角色: HTTP请求的发起方
常见类型: 浏览器(Chrome/Firefox/Safari)、开发者工具(Postman/cURL)、爬虫程序。
特殊场景:1
2# 开发者调试示例
curl -X GET https://api.example.com/users - 服务端 (Web Server)
核心职能: 接收请求、处理业务逻辑、返回HTTP响应。
典型工作流: - 代理服务器 (Proxies)
网络位置: 位于客户端与服务端之间。
核心功能:功能类型 作用描述 技术实现示例 缓存代理 减少源站压力 Cache-Control头控制 安全网关 病毒扫描/内容过滤 深度包检测(DPI) 负载均衡 流量分发 轮询/一致性哈希算法 访问控制 权限验证 JWT/OAuth2.0 日志记录 流量监控与分析 ELK日志系统
透明代理示例:
1 | GET / HTTP/1.1 |
HTTP 报文详解
HTTP 报文组成
请求报文
请求报文 由起始行
、请求头
、空行
和请求体
组成。
起始行:
组成部分 | 详情 | 示例 |
---|---|---|
请求方法 | 规定客户端对服务器资源的操作类型 | GET、POST、PUT、DELETE 等 |
请求路径 | 标识请求资源在服务器上的位置 | 绝对路径: GET /resource.txt HTTP/1.1 完整 URL: GET http://www.example.com/page.html HTTP/1.1 authority form: CONNECT proxy.example.com:80 HTTP/1.1 星号形式: OPTIONS * HTTP/1.1 |
HTTP 版本号 | 表明使用的 HTTP 协议版本 | HTTP/1.1、HTTP/2 等 |
请求头: 不区分大小写的字符串,格式为 属性名: 属性值
,用于服务端获取客户端基本信息。
属性名 | 属性值 |
---|---|
Accept | 览器支持的 MIME 媒体类型, 比如 text/html,application/json 等 |
Accept-Encoding | 浏览器发给服务器,声明浏览器支持的编码类型,gzip, deflate |
Accept-Language | 客户端接受的语言格式,比如 zh-CN |
Connection | keep-alive , 开启 HTTP 持久连接 |
Host | 服务器的域名。 |
Origin | 告诉服务器请求从哪里发起的,仅包括协议和域名 CORS 跨域请求中可以看到 response 有对应的 header,Access-Control-Allow-Origin。 |
Referer | 告诉服务器请求的原始资源的 URI,其用于所有类型的请求,并且包括: 协议+域名+查询参数; 很多抢购服务会用这个做限制,必须通过某个入来进来才有效。 |
User-Agent | 服务器通过这个请求头判断用户的软件的应用类型、操作系统、软件开发商以及版本号、浏览器内核信息等; 风控系统、反作弊系统、反爬虫系统等基本会采集这类信息做参考。 |
Cookie | 表示服务端给客户端传的 http 请求状态,也是多个 key=value 形式组合,比如登录后的令牌等。 |
Content-Type | HTTP 请求提交的内容类型,post 提交时才需要设置,比如文件上传,表单提交、json 等。 |
form 表单提交 | application/x-www-form-urlencoded。 |
json 方式提交 | application/json。 |
空行: 容易被忽略,但必不可少。
请求体: 有些请求(如 POST)将数据发送到服务器,数据类型常见有通过 Content-Type 和 Content-Length 定义的单文件 body,以及由多 Body 组成(通常和 HTML Form 联系在一起)。application/x-www-form-urlencoded 格式表单内容,数据会编码成以 & 分隔的键值对,字符以 URL 编码方式编码;multipart/form-data 格式,请求头中的 Content-Type 字段会包含 boundary(由浏览器默认指定),数据分为多个部分,每部分由 HTTP 头部描述子包体,最后分隔符加 – 表示结束。
响应报文
响应报文 由起始行
、响应头
、空行
和响应体
组成。
起始行: 包含 HTTP 版本号、响应状态码(如 200、404 等)和状态文本描述(如 OK、Not Found 等)。
响应头:
属性名 | 属性值 |
---|---|
Allow | 服务器支持哪些请求方法。 |
Content-Length | 响应体的字节长度。 |
Content-Type | 响应体的 MIME 类型。 |
Content-Encoding | 设置数据使用的编码类型。 |
Date | 设置消息发送的日期和时间。 |
Expires | 设置响应体的过期时间,一个 GMT 时间,表示该缓存的有效时间。 |
cache-control | Expires 的作用一致,都是指明当前资源的有效期, 控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据,优先级高于 Expires,控制粒度更细,如 max-age=240,即 4 分钟。 |
Location | 表示客户应当到哪里去获取资源,一般同时设置状态代码为 3xx。 |
Server | 服务器名称。 |
Transfer-Encoding | chunked 表示输出的内容长度不能确定,静态网页一般没,基本出现在动态网页里面。 |
Access-Control-Allow-Origin | 指定哪些站点可以参与跨站资源共享。 |
空行: 分隔响应头和响应体。
响应体: 包含请求结果数据,常见格式有 html、json、图片、视频文件等。响应体类型由 Content-Type 指定,已知长度的单个文件由 Content-Type 和 Content-Length 定义,未知长度的单个文件通过将 Transfer-Encoding 设置为 chunked 来使用 chunks 编码。
Content-Type 媒体类型
常见取值:
属性名 | 属性值 |
---|---|
text/html | HTML 格式 |
text/plain | 纯文本 |
text/xml | XML 格式 |
image/* | 各种图片格式 |
application/json | JSON 数据 |
application/pdf | PDF 文档 |
application/octet-stream | 二进制流(文件下载) |
application/x-www-form-urlencoded | 表单默认提交格式 |
multipart/form-data | 文件上传格式 |
常见请求方法
HTTP/1.0 定义的方法:
GET: 获取资源,是安全且幂等的(理论上不会对服务器资源产生副作用,多次相同请求服务器资源状态一致),请求能缓存,但请求参数在 URL 中,不太安全且有长度限制。
POST: 提交数据,数据放在请求体中,相对安全,没有数据类型限制,不幂等(多次相同请求可能会对服务器资源产生不同影响),一般不能缓存。
HEAD: 与 GET 类似,但服务器响应只返回首部,不返回实体主体部分。
HTTP/1.1 定义的方法:
PUT: 全量更新资源,是幂等的(多次相同请求服务器资源状态一致)。
PATCH: PUT 方法的补充,部分更新资源。
DELETE: 删除资源。
OPTIONS: 获取服务器支持的请求方法,也可用于服务器性能检测、跨域检查等。
CONNECT: 把服务器作为跳板,建立隧道连接(用于代理)。
TRACE: 回显服务器收到的请求,主要用于测试或诊断。
响应码分类
分类 | 范围 | 代表状态码 | 触发场景 |
---|---|---|---|
信息 | 100-199 | 101 | WebSocket 升级 |
成功 | 200-299 | 200/204 | 常规请求/无内容 |
重定向 | 300-399 | 301/302/304 | 永久跳转/临时跳转/缓存有效 |
客户端错误 | 400-499 | 400/403/404 | 参数错误/无权限/资源不存在 |
服务端错误 | 500-599 | 500/503 | 代码异常/服务不可用 |
HTTP 的前世今生
HTTP 0.9 (1991)
单行协议: 仅支持GET方法。
简单响应: 只返回纯HTML内容。
无状态码/头部: 功能极其有限。
1 | GET /page.html |
响应: 只包括响应文档本身。
1 | <HTML> |
没有响应头,只传输 HTML 文件,没有状态码。
HTTP 1.0 (1996)
RFC 1945 提出了 HTTP1.0,构建更好可拓展性
引入头部: 支持元数据传输。
状态码: 响应状态标准化。
内容类型: 通过Content-Type支持多种文件格式。
短连接: 每个请求需新建TCP连接。
问题: 频繁建立连接导致性能低下。
HTTP 1.1 (1997)
持久连接: 默认Connection: keep-alive。
管道化: 允许连续发送多个请求(但仍有队头阻塞)。
分块传输: Transfer-Encoding: chunked。
虚拟主机: Host头支持。
缓存增强: ETag/Cache-Control等。
问题: 头部重复传输、队头阻塞未彻底解决。
HTTP/2 (2015)
二进制协议: 取代文本格式。
多路复用: 彻底解决队头阻塞。
头部压缩: HPACK算法。
服务器推送: 主动推送资源。
流优先级: 优化资源加载顺序。
核心改进: 单个连接并行处理多个请求。
HTTP/3 (2018)
QUIC协议: 基于UDP实现。
0-RTT: 快速重连。
改进的多路复用: 避免TCP队头阻塞。
前向纠错: 增强弱网环境稳定性。
特点: 专注于传输层优化,逐步被主流浏览器支持。