HTTP 与 HTTPS 工作原理小结
刚学做网站那阵子,我对 HTTP 的理解就一句话:「加个 s 就安全了」。真正开始自己配服务器、自己签证书、对着抓包工具一条条看报文,才发现中间发生的事情比想象的多得多,也比想象的有意思。这篇按"一次访问从头到尾"的顺序写,把这条链路上每个环节都摊开讲一遍——不追求学术严谨,追求的是"看完之后,再配 nginx 或 Caddy 心里有底"。
一、从敲下回车到看见页面,中间跑了几步
这件事我一开始完全没概念,以为"输入网址 → 页面出现"是一步。其实拆开至少有六步,每一步都能出问题。按顺序走一遍:
- 地址被解析成 IP。浏览器先看本地缓存里有没有记过这个域名,没有就问 DNS,拿到一个 IP 地址。这一步的耗时完全取决于缓存命中情况——本机或路由器上有没有配 DNS 缓存,体感差别巨大。
- 建立一条 TCP 连接。拿到 IP 之后,客户端要和对方在 443(或 80)端口上"握一次手",双方确认能通、能收能发。这一步就是常说的"三次握手",网络延迟高的时候,它就占掉了总耗时的一大块。
- 如果是 HTTPS,还要再握手一次。这次是 TLS 层面的,目的有两个:验证对方的身份是不是真的持证,以及商量出一个双方共用的加密方式。这一步是最容易配错的地方,后面单独说。
- 发出请求。客户端把"我要哪个路径、我支持什么格式、带没带凭据"这些信息组装成一段文本发出去。这段文本就是 HTTP 报文,结构非常朴素,后面贴给你看。
- 对方处理并返回。服务器上的程序(可能是静态文件,也可能是自己写的程序)根据路径决定给什么,然后把结果连同状态码、内容类型一起回过来。
- 浏览器负责渲染。拿到 HTML 之后,浏览器再按里面的引用去要 CSS、图片、脚本,一轮轮重复上面的过程。所以打开一个页面其实不是一次请求,而是十几次甚至几十次。
理解这条链路最大的好处,是排查问题时不再瞎猜。打不开页面的时候,我会按这个顺序问自己:域名能不能解析?端口通不通?证书有没有过期?内容路径对不对?四问下来,问题基本就定位了。
二、请求和响应到底长什么样
很多人以为 HTTP 报文是某种二进制协议,其实它就是纯文本——几行头信息加一个空行,后面跟正文。用 curl 看一眼就明白了:
# 看请求和响应头,-I 表示只要头不要正文
curl -I https://example.com
# 结果长这样:
HTTP/2 200 ← 状态行
content-type: text/html; charset=utf-8
content-length: 1256
cache-control: max-age=3600
date: Wed, 24 Sep 2026 12:00:00 GMT
结构就是三块:状态行(协议版本 + 状态码 + 说明)、头信息(键值对,一行一个)、空行之后是正文。请求也是同样的结构,只是第一行变成了「方法 + 路径 + 版本」:
GET /articles/linux.html HTTP/1.1 ← 方法 + 路径 + 版本
Host: example.com
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Encoding: gzip
← 这个空行很关键,它分隔头部和正文
(正文:POST 时才有)
方法里最常用的就四个,各自的分工其实很好记:
| 方法 | 语义 | 有没有正文 | 典型场景 |
|---|---|---|---|
GET | 读取 | 无 | 打开页面、取列表、下载文件 |
POST | 提交 | 有 | 表单提交、上传数据 |
PUT / PATCH | 更新整体 / 局部 | 有 | 修改一条已有记录 |
DELETE | 删除 | 无 | 删掉一条记录 |
GET 的查询参数会完整出现在地址栏和日志里,所以凡是带凭据的东西,一概不能放 GET。我早期的配置里图省事把一串密钥写在地址里,后来看访问日志才发现全躺在里面。三、状态码记五类就够,不用记一百个
状态码看起来很多,规律却特别简单——第一位数字就说明了结局的大类。记住五个大类,具体数字用到再查:
| 范围 | 含义 | 日常最常碰到的 |
|---|---|---|
1xx | 信息,连接还在协商 | 几乎见不到,遇到说明用了新的传输方式 |
2xx | 成功 | 200 正常;204 成功但没有内容 |
3xx | 跳转 | 301 永久跳(换域名用);302 临时跳;304 缓存还有效,别再传了 |
4xx | 请求方的问题 | 403 权限不足;404 路径不存在;429 请求太频繁被限流 |
5xx | 服务器自己的问题 | 500 程序抛异常;502 反代后面那个程序没起来;504 后面那个程序响应超时 |
404 和 403 的分工最能反映配置水平。404 是"没这个路径",403 是"有这个东西但不让你看"。配静态站点的时候如果整站都报 403,八成是目录缺了执行权限或者没有默认首页——不是文件不存在。四、HTTPS 到底多做了什么
HTTPS 等于「HTTP 报文」被塞进了一个加密通道里运输,通道本身由 TLS 提供。它要解决三个问题:内容别被人看、内容别被人改、对面确实是它本人。前两个靠加密,第三个靠证书。
证书里装的是三样东西:这个域名、一把公钥、签发机构的签名。浏览器内置了一批受信任的签发机构名单,只要能顺着证书链验到名单里的某一个,就认为"这个域名确实由它持有"。整条链路里最关键的一点是:证书必须用域名去签——给 a.example.com 签的证书,拿去给 b.example.com 用,浏览器会直接报错。
五、配 HTTPS 时我踩过的几个坑
:443 反而不认。curl -I http://127.0.0.1:8000。能通说明程序没问题,问题在证书或反代这一层;不能通说明程序本身没起来。这一招能把排查范围一次砍掉一半。小结
把这条链路理清楚之后,我的实际收益是三件事:
- 配反向代理不再是复制粘贴。知道每个配置项在链路哪一环起作用,出问题知道去哪找。
- 排错有了固定顺序。域名解析 → 端口连通 → 证书验证 → 路径匹配,四步走完问题必现形。
- 明白"https 不是可选项"。对外的访问入口现在基本都强制加密,而且是标准端口,这不是趋势,是当下的门槛。