HTTP / HTTPS(应用层协议)
1. 定义
HTTP (HyperText Transfer Protocol,超文本传输协议) 是 Web 的应用层协议,规定了客户端(浏览器)和服务器之间怎么请求、怎么响应——用什么格式发、有哪些方法、返回什么状态码。它跑在传输层 TCP 之上(HTTP/3 例外,跑在 UDP/QUIC 上)。
HTTPS = HTTP + TLS 加密。就是在 HTTP 和 TCP 之间加了一层 TLS,把明文传输变成加密传输。
一句话概括:HTTP 是浏览器和服务器之间的”对话规则”——一问一答、无状态、纯文本格式,简单到人都能读懂。
类比:HTTP 像点餐的标准话术。顾客(客户端)说”我要一份 /menu”(请求),后厨(服务器)回”好的,这是你的菜 200 OK”(响应)。规矩定死了怎么问怎么答,双方才能配合。HTTPS 就是把这段对话装进保密信封,中间传菜的人看不到内容。
2. HTTP 的三个核心特点
| 特点 | 含义 | 带来的影响 |
|---|---|---|
| 请求-响应 | 客户端发起,服务器回应,永远一问一答 | 服务器不能主动推送(要推送得用 WebSocket/SSE) |
| 无状态 (stateless) | 每个请求相互独立,服务器默认不记得你 | ”记住登录”要靠 Cookie/Session/Token 补 |
| 纯文本 (HTTP/1.x) | 报文是人类可读的文本 | 易调试,但体积大、效率低(HTTP/2 起改二进制) |
无状态是最重要的一点,它解释了 Web 开发一大堆机制的存在理由——见第 7 节会话保持,也呼应
server.md第 9 节。
3. 报文格式(一问一答长什么样)
请求报文:
GET /index.html HTTP/1.1 ← 请求行:方法 + 路径 + 协议版本
Host: example.com ← 请求头(headers):一堆 key: value
User-Agent: Mozilla/5.0
Accept: text/html
Cookie: sessionId=abc123
← 空行:分隔头部和主体
(GET 通常无主体;POST 的表单/JSON 放这里)响应报文:
HTTP/1.1 200 OK ← 状态行:协议 + 状态码 + 描述
Content-Type: text/html; charset=utf-8 ← 响应头
Content-Length: 1234
Set-Cookie: sessionId=abc123 ← 服务器给浏览器"发身份牌"
← 空行
<html>...</html> ← 响应主体:真正的内容可以用
curl -v https://example.com亲眼看到这些报文。
4. 请求方法 (Method)
| 方法 | 语义 | 幂等? | 典型用途 |
|---|---|---|---|
| GET | 获取资源 | 是 | 读取数据,参数放 URL |
| POST | 提交数据 | 否 | 新建资源、提交表单,数据放主体 |
| PUT | 整体替换/创建 | 是 | 更新整个资源 |
| PATCH | 局部更新 | 否 | 只改部分字段 |
| DELETE | 删除资源 | 是 | 删除 |
| HEAD | 只要响应头不要主体 | 是 | 检查资源是否存在/是否更新 |
| OPTIONS | 询问支持哪些方法 | 是 | CORS 预检 |
幂等 (idempotent):同样的请求发一次和发多次,对服务器的效果一样。GET/PUT/DELETE 幂等(删一次和删两次结果都是”没了”);POST 不幂等(提交两次可能下两个订单)——所以刷新提交页面浏览器会警告”是否重新提交表单”。
5. 状态码 (Status Code)
| 段 | 含义 | 常见 |
|---|---|---|
| 1xx | 信息,处理中 | 101 切换协议(升级 WebSocket) |
| 2xx | 成功 | 200 OK、201 Created、204 No Content |
| 3xx | 重定向 | 301 永久跳转、302 临时、304 命中缓存不用重传 |
| 4xx | 客户端错 | 400 格式错、401 未认证、403 无权限、404 找不到、429 请求太频繁 |
| 5xx | 服务器错 | 500 内部错误、502 网关错误、503 不可用、504 网关超时 |
记法:4xx 你(客户端)的锅,5xx 我(服务器)的锅。 排错先看状态码定位方向。
401(没登录)和403(登录了但没权限)容易混:401=你是谁不知道,403=知道你是谁但不让你进。
6. 关键请求头/响应头(高频)
| 头 | 方向 | 作用 |
|---|---|---|
Host | 请求 | 访问哪个域名(一台服务器靠它区分多个网站) |
Content-Type | 双向 | 主体是什么格式:application/json、text/html、multipart/form-data |
Content-Length | 双向 | 主体字节数 |
Authorization | 请求 | 携带认证信息,如 Bearer <token> |
Cookie / Set-Cookie | 请求/响应 | 会话保持(见第 7 节) |
Cache-Control | 双向 | 缓存策略:no-cache、max-age=3600 |
User-Agent | 请求 | 客户端标识(浏览器/爬虫类型) |
Location | 响应 | 配合 3xx,告诉浏览器跳转到哪 |
7. 无状态怎么”记住你”:Cookie / Session / Token
HTTP 无状态,服务器认人靠这套(详见 server.md 第 9 节):
首次登录:
客户端 ──── POST /login (账号密码) ────▶ 服务器
客户端 ◀── 200 + Set-Cookie: id=abc ──── 服务器(发身份牌)
后续请求:
客户端 ──── GET /profile Cookie: id=abc ────▶ 服务器(每次自动带上身份牌)
服务器凭 id 认出"这是刚才登录的人"
- Cookie:浏览器自动保存并每次带上的小数据。
- Session:状态存在服务器端,Cookie 里只放个 sessionId 当钥匙。→ 多机部署时 Session 要集中存(如 Redis)。
- Token (JWT):状态签名后交客户端保管,服务器不用存,天然适合分布式。
8. HTTPS:HTTP 怎么变安全
HTTP 明文传输,中间任何节点都能看/改。HTTPS 在 TCP 和 HTTP 之间插一层 TLS:
应用层 HTTP
│
安全层 TLS ← HTTPS 多出来的这层:加密 + 身份验证 + 完整性
│
传输层 TCP
TLS 解决三件事:
- 加密 (Confidentiality):内容被窃听也看不懂。
- 身份验证 (Authentication):靠证书确认”对方真是 example.com”,不是钓鱼站冒充。
- 完整性 (Integrity):内容被中途篡改能发现。
TLS 握手(简化):非对称加密协商出一个对称密钥,之后用对称加密传数据(对称快,非对称安全但慢,取两者之长)。
客户端 ─ 我支持这些加密套件 ─▶ 服务器
客户端 ◀─ 选这个套件 + 我的证书(含公钥) ─ 服务器
客户端 ── 用公钥加密一个随机数发过去 ──▶ 服务器(只有服务器私钥能解)
双方由此算出同一把对称密钥 ── 之后全用它加密通信
证书由受信任的 **CA(证书颁发机构)**签发,浏览器内置了信任的 CA 列表。证书过期/自签/域名不符,浏览器就报”不安全”。Let’s Encrypt 提供免费证书。
9. HTTP 版本演进(为什么越来越快)
| 版本 | 底层 | 关键改进 | 解决的问题 |
|---|---|---|---|
| HTTP/1.0 | TCP | 每个请求新建一个连接 | — |
| HTTP/1.1 | TCP | 长连接 (keep-alive) 复用、管线化 | 省掉反复握手,但仍有队头阻塞 |
| HTTP/2 | TCP | 二进制分帧、多路复用、头部压缩、服务器推送 | 一个连接并发多请求,解决 HTTP 层队头阻塞 |
| HTTP/3 | UDP/QUIC | 换到 QUIC | 解决 TCP 层队头阻塞(丢一个包不再卡住所有流),握手更快 |
队头阻塞 (Head-of-Line Blocking) 是这条演进线的主线:HTTP/1.1 一个连接里请求得排队 → HTTP/2 在应用层用多路复用解决,但底层 TCP 丢包仍会卡住整条连接 → HTTP/3 干脆换 UDP,让各个流互不影响。呼应
tcp-udp.md第 7 节”为什么 HTTP/3 从 TCP 换回 UDP”。
10. 常见坑 / 误区
- ❌ “HTTPS 只是加密” → 不只,还有身份验证(防钓鱼)和完整性(防篡改)
- ❌ “有了 HTTPS 就绝对安全” → 只保护传输链路;服务器被黑、XSS、弱密码等它管不了
- ❌ “GET 和 POST 只是参数位置不同” → 语义也不同:GET 幂等且可缓存、参数在 URL(有长度限制、会被日志记录,别放敏感信息);POST 不幂等、数据在主体
- ❌ “GET 请求不会改数据所以安全” → 语义上不该改,但如果后端写成 GET 也能改数据,就会被 CSRF 等利用;要遵守方法语义
- ❌ “404 是服务器出错了” → 404 是 4xx,属客户端错(路径不存在);服务器崩了是 5xx
- ❌ “Cookie 存在服务器上” → Cookie 存在浏览器,Session 才存服务器;Cookie 里通常只放 sessionId
- ❌ “HTTP/2 就不用管 TCP 队头阻塞了” → HTTP/2 只解决了应用层的,TCP 层的要靠 HTTP/3(QUIC) 才解决
- ❌ “把 token/密码放 URL 里” → URL 会被浏览器历史、服务器日志、Referer 泄露,敏感信息放主体或 Authorization 头
11. 延伸阅读 / 关联概念
- TCP / UDP — HTTP 的传输层底座,理解队头阻塞的关键;见
tcp-udp.md - Socket — HTTP 服务器底层用 socket 收发;见
socket.md - 服务器原理 — 请求-响应、状态码、会话保持的宿主;见
server.md - 静态 vs 动态网页 — 服务器如何生成 HTTP 响应内容;见
../web/static-vs-dynamic-pages.md - DNS 解析绑定 — 发 HTTP 请求前先解析域名;见
dns-binding.md - WebSocket — 在 HTTP 之上升级成的全双工长连接,解决”服务器不能主动推”的问题
- TLS / 证书 / CA — HTTPS 安全的基础
- CORS — 跨域资源共享,OPTIONS 预检的由来
- HTTP 方法与 Fetch API — 怎么用 Fetch/curl 真正发出这些动词(实践层);见
http_methods_fetch.md