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

HTTP 协议详解教程 / 第 1 章:HTTP 概述与历史

第 1 章:HTTP 概述与历史

HTTP 是互联网上应用最广泛的协议之一。理解它的历史演进与核心设计哲学,是深入学习的第一步。


1.1 什么是 HTTP

HTTP(Hypertext Transfer Protocol,超文本传输协议) 是一种用于分布式、协作式、超媒体信息系统的应用层协议。它是万维网(World Wide Web)的数据通信基础。

核心特征

特征说明
客户端-服务器模型客户端发起请求,服务器返回响应
无状态(Stateless)每个请求独立,服务器不保留之前的请求信息
可扩展通过自定义头部字段和方法扩展功能
基于文本HTTP/1.x 使用人类可读的文本格式
传输层无关理论上可运行在任何可靠的传输层之上

1.2 HTTP 的历史演进

版本时间线

1991 ── HTTP/0.9    ── 最初版本,仅支持 GET
1996 ── HTTP/1.0    ── RFC 1945,引入头部字段、状态码
1997 ── HTTP/1.1    ── RFC 2068 → RFC 2616 → RFC 9112,持久连接、分块传输
2015 ── HTTP/2      ── RFC 7540 → RFC 9113,多路复用、头部压缩
2022 ── HTTP/3      ── RFC 9114,基于 QUIC(UDP)

HTTP/0.9(1991)

最初的 HTTP 由 Tim Berners-Lee 在 CERN 设计,极其简单:

GET /index.html

响应直接返回 HTML,没有头部、没有状态码:

<html>
<body>Hello World</body>
</html>

📝 注意:HTTP/0.9 没有任何元数据机制,无法传输非 HTML 内容。

HTTP/1.0(1996)

引入了关键特性:

GET /page.html HTTP/1.0
Host: www.example.com
User-Agent: Mozilla/5.0

HTTP/1.0 200 OK
Date: Tue, 15 Nov 2024 08:12:31 GMT
Content-Type: text/html
Content-Length: 137

<html><body>Hello</body></html>

新增特性:

  • 版本号随请求行发送
  • 状态码(如 200、404)
  • 头部字段(Content-Type、User-Agent 等)
  • 支持非 HTML 内容(图片、视频等)

局限:

  • 每个请求/响应后关闭 TCP 连接
  • 无法在一个连接上发送多个请求

HTTP/1.1(1997)

HTTP/1.1 是使用时间最长的版本,核心改进:

改进项说明
持久连接默认开启 Connection: keep-alive,复用 TCP 连接
Host 头必须包含 Host,支持虚拟主机
分块传输Transfer-Encoding: chunked
缓存增强ETag、If-None-Match 等协商缓存机制
管道化允许在同一连接上连续发送多个请求(实际支持有限)
GET /index.html HTTP/1.1
Host: www.example.com
Connection: keep-alive

GET /style.css HTTP/1.1
Host: www.example.com
Connection: keep-alive

HTTP/2(2015)

HTTP/2 由 Google 的 SPDY 协议演进而来:

特性说明
二进制分帧不再是纯文本,使用二进制帧
多路复用一个 TCP 连接上并发多个请求/响应
头部压缩HPACK 算法压缩头部,减少冗余
服务器推送服务器主动推送资源
流优先级客户端可指定请求优先级
# 使用 Python 演示 HTTP/2 客户端
import httpx

async def fetch_http2():
    async with httpx.AsyncClient(http2=True) as client:
        response = await client.get("https://www.example.com")
        print(f"HTTP 版本: {response.http_version}")  # HTTP/2
        print(f"状态码: {response.status_code}")

HTTP/3(2022)

HTTP/3 的最大变化是传输层从 TCP 改为 QUIC(基于 UDP):

传统:  HTTP → TCP → IP
HTTP/3: HTTP → QUIC(UDP) → IP

核心优势:

优势说明
消除队头阻塞丢包只影响单个流,不阻塞其他流
0-RTT 连接首次连接后可实现零往返延迟
连接迁移网络切换(WiFi → 4G)连接不断
内置 TLS 1.3安全性开箱即用

1.3 请求-响应模型

HTTP 采用经典的 客户端-服务器(Client-Server) 模型:

┌──────────┐         请求 (Request)        ┌──────────┐
│          │ ─────────────────────────────→ │          │
│  Client  │                                │  Server  │
│          │ ←───────────────────────────── │          │
└──────────┘        响应 (Response)         └──────────┘

请求的组成

GET /api/users?page=1 HTTP/1.1          ← 请求行 (Method + Path + Version)
Host: api.example.com                    ← 请求头
Accept: application/json
Authorization: Bearer eyJhbG...

                                     ← 空行
                                     ← 请求体(GET 无)

响应的组成

HTTP/1.1 200 OK                          ← 状态行 (Version + Status + Reason)
Content-Type: application/json           ← 响应头
Content-Length: 85
Cache-Control: max-age=3600

{"users": [{"id": 1, "name": "Alice"}]}  ← 响应体

完整示例:用 Python 发送请求与响应

# server.py — 一个简单的 HTTP 服务器
import json
from http.server import HTTPServer, BaseHTTPRequestHandler

class SimpleHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/api/hello':
            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            body = json.dumps({"message": "Hello, HTTP!"})
            self.wfile.write(body.encode())
        else:
            self.send_response(404)
            self.send_header('Content-Type', 'text/plain')
            self.end_headers()
            self.wfile.write(b'Not Found')

if __name__ == '__main__':
    server = HTTPServer(('localhost', 8080), SimpleHandler)
    print("Server running on http://localhost:8080")
    server.serve_forever()
# 启动服务器
python server.py

# 发送请求
curl http://localhost:8080/api/hello
# 输出: {"message": "Hello, HTTP!"}

1.4 无状态特性

HTTP 是 无状态协议(Stateless Protocol)——每个请求都是独立的,服务器不会"记住"之前的请求。

无状态的含义

请求 1: GET /login  ──→ 服务器处理,返回成功
请求 2: GET /profile ──→ 服务器不认识你,因为不知道你已经登录

为什么设计为无状态?

优势说明
简单服务器无需维护会话状态
可伸缩请求可被任意服务器处理,便于水平扩展
可靠性单个服务器故障不影响其他请求
缓存友好无状态的响应更容易缓存

如何实现"有状态"的应用?

尽管 HTTP 无状态,实际应用中我们需要状态管理:

方案原理适用场景
Cookie服务器通过响应设置 Cookie,客户端自动携带浏览器会话
Session服务端存储会话数据,客户端通过 Cookie 中的 Session ID 访问传统 Web 应用
Token (JWT)服务器签发令牌,客户端每次请求携带API、移动端
URL 参数将状态信息放在 URL 中分页、简单状态
# 用 Cookie 实现有状态的请求
import requests

session = requests.Session()

# 登录 — 服务器设置 Session Cookie
session.post("https://example.com/login", data={
    "username": "alice",
    "password": "secret"
})

# 后续请求自动携带 Cookie
profile = session.get("https://example.com/profile")
print(profile.json())

1.5 HTTP 的适用场景

适合的场景

场景原因
Web 页面浏览HTTP 的本职工作
RESTful API无状态、标准化,非常适合 API 设计
文件传输支持大文件、断点续传
微服务通信服务间通过 HTTP/gRPC 通信
物联网(IoT)轻量级请求,CoAP 基于类似模型

不太适合的场景

场景问题替代方案
实时双向通信HTTP 是单向请求模型WebSocket
高频推送轮询效率低SSE / WebSocket / gRPC streaming
极低延迟TCP 握手 + TLS 开销QUIC (HTTP/3) / UDP 协议
广播/组播HTTP 是一对一模型MQTT / AMQP

1.6 业务场景:电商网站的 HTTP 请求

以下是一个典型电商网站页面加载时的 HTTP 请求序列:

1. GET  /index.html           → 获取 HTML 文档
2. GET  /style.css            → 获取样式表
3. GET  /app.js               → 获取 JavaScript
4. GET  /api/products         → 获取商品列表 (API)
5. GET  /image/product1.jpg   → 获取商品图片
6. POST /api/cart             → 添加商品到购物车
7. GET  /api/user/profile     → 获取用户信息(携带 Token)
# 用 curl 模拟以上流程
# 1. 获取首页
curl -O https://shop.example.com/index.html

# 2. 调用 API(带认证)
curl -H "Authorization: Bearer <token>" \
     -H "Accept: application/json" \
     https://shop.example.com/api/products

# 3. 添加购物车
curl -X POST \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer <token>" \
     -d '{"product_id": 42, "quantity": 1}' \
     https://shop.example.com/api/cart

1.7 HTTP 与其他协议的对比

协议层级传输方式典型应用
HTTP应用层请求-响应Web、API
WebSocket应用层全双工实时聊天、游戏
gRPC应用层(HTTP/2)远程过程调用微服务
FTP应用层文件传输大文件上传下载
SMTP应用层邮件发送邮件系统
MQTT应用层发布-订阅IoT、消息推送

⚠️ 注意事项

  1. HTTP 与 HTTPS:HTTP 本身不加密,HTTPS = HTTP + TLS,生产环境必须使用 HTTPS
  2. 版本兼容:HTTP/1.1 仍是使用最广泛的版本,但 HTTP/2 正在快速普及
  3. 无状态不等于无会话:应用层可以通过 Cookie/Token 实现会话管理
  4. HTTP/2 需要 TLS:虽然规范不要求,但浏览器都要求 HTTP/2 必须使用 TLS

🔗 扩展阅读


下一章第 2 章:HTTP 基础要素 — 请求方法、状态码、头部字段、消息结构