Skip to main content

HTTP

HTTP 协议与演进

1. HTTP 状态码

状态码分类:1xx (信息),2xx (成功),3xx (重定向),4xx (客户端错误),5xx (服务端错误)。

面试必考细分场景:

  • 101 Switching Protocols:协议升级。常见于 WebSocket 握手时,服务器同意将 HTTP 协议升级为 WebSocket 协议。
  • 204 No Content:请求成功,但响应无返回内容。常见于 DELETE 操作,或跨域 OPTIONS 预检请求的成功响应。
  • 206 Partial Content:服务器成功处理了部分范围请求。这是大文件分块下载 / 断点续传的核心状态码。
  • 301 Moved Permanently vs 302 Found
    • 301 是永久重定向。浏览器会缓存这个重定向,对 SEO 友好(常用于旧域名迁移)。如果用户把旧 URL 加入书签,浏览器会自动将其更新为新 URL
    • 302 是临时重定向。浏览器不会缓存。容易被网络劫持(URL 劫持):因为 302 是临时的,搜索引擎会保留旧 URL 但抓取新内容,黑客可以利用这一点用恶意域名 302 指向合法网站,从而在搜索结果中占位;同时由于不被浏览器缓存,中间人(如运营商)更容易通过拦截并伪造 302 响应来插入广告。常用于未登录拦截跳登录页。书签依然会保留旧的 URL
  • 304 Not Modified协商缓存命中!告诉客户端直接使用本地缓存。
  • 400 Bad Request:客户端发送的请求有语法错误(比如少传了必填参数,或者 JSON 格式不对),服务端无法理解。
  • 401 Unauthorized vs 403 Forbidden
    • 401:你没有登录(没有身份凭证 Token,或者 Token 过期)。
    • 403:你登录了,但你的角色(权限)不足以访问该资源。
  • 405 Method Not Allowed:请求方法不被允许。比如接口只支持 POST,你却用 GET 去请求。
  • 502 Bad Gateway vs 504 Gateway Timeout
    • 502:网关(如 Nginx)收到了来自上游后端服务器的无效响应(比如后端 Node 进程崩溃了)。
    • 504:网关等待上游后端服务器响应超时(比如后端在执行一个长达 2 分钟的死循环或者慢查询)。

2. 常见 HTTP 标头 (Headers)

核心请求头

  • Accept:声明客户端可处理的响应内容类型(如 application/json)。
  • Accept-Encoding:告诉服务器客户端支持的压缩算法(如 gzip, deflate, br)。
  • Authorization:携带身份凭证(如 Bearer <token>)。
  • Content-Type:指定请求体的数据类型(POST/PUT 必需,如 application/jsonmultipart/form-data)。
  • Host:目标服务器的域名和端口(HTTP/1.1 必须包含)。
  • Origin(跨域核心) 指示请求发起的源(协议+域名+端口)。与 Referer 不同,它不包含具体路径,常用于 CORS 请求和 CSRF 防护。
  • Referer:标记请求的来源完整 URL(常用于防盗链或日志分析)。
  • User-Agent:标识客户端的浏览器、操作系统等信息(常用于服务端判断设备类型或处理兼容性)。
  • Connection:控制当前网络连接是否保持。keep-alive 表示复用 TCP 连接。
  • Cookie:客户端存储的 Cookie 字符串,每次请求会自动带上。

核心响应头

  • Content-Type:声明响应体的实际媒体类型。
  • Content-Encoding:实际使用的压缩格式(需客户端解压)。
  • Cache-Control(绝对核心) 指导强缓存策略,如 max-age=3600no-cache
  • ETag / Last-Modified:用于协商缓存的资源标识符和最后修改时间。
  • Set-Cookie:服务端向客户端设置 Cookie。包含 HttpOnlySameSiteSecure 等关键安全属性。
  • Location:用于重定向的目标 URL(配合 3xx 状态码使用)。
  • Access-Control-Allow-Origin:解决跨域资源共享(CORS)的关键,指定允许访问的域名。
  • Vary:告知缓存服务器,如何根据请求头(如 Accept-Encoding)来决定是否使用缓存。
  • Server:告知客户端服务端使用的软件信息(如 nginx/1.18.0)。

HTTP 协议的演进史

面试官经常会问:“请简述 HTTP 1.0 到 HTTP 3.0 的演进过程以及解决了什么问题?”

HTTP/1.0 与 HTTP/1.1

  • HTTP/1.0 的痛点:每次请求都必须建立一次 TCP 连接(三次握手),请求完立刻断开,开销极大。
  • HTTP/1.1 的改进
    • 长连接 (Keep-Alive):默认开启,多个 HTTP 请求可以复用同一个 TCP 连接。
    • 管道化 (Pipelining):允许客户端同时发出多个请求,但服务器必须按顺序响应,这就导致了致命的HTTP 队头阻塞(前一个请求太慢会卡住后面所有的响应)。
    • 支持断点续传:引入了 Range 请求头和 206 状态码。

HTTP/2 (性能质的飞跃)

  • 二进制分帧:HTTP/1.x 是文本协议,解析慢;HTTP/2 是二进制协议,将数据拆分为更小的帧 (Frame) 和流 (Stream)。
  • 多路复用 (Multiplexing)彻底解决了 HTTP 层的队头阻塞! 在同一个 TCP 连接里,多个请求可以完全乱序、并行地发送和接收数据,浏览器通过 Stream ID 来重组数据。
  • 头部压缩 (HPACK):HTTP/1.x 每次都要发送重复的 Header(如 Cookie),HTTP/2 通过 HPACK 算法在客户端和服务端维护了一张字典表,大大压缩了头部体积。
  • 服务器推送 (Server Push):服务器可以主动向客户端推送后续需要的资源。

面试追问:HTTP/2 这么好,有什么缺点? 虽然解决了 HTTP 层的队头阻塞,但没有解决 TCP 层的队头阻塞。TCP 是保证可靠传输的,如果底层网络丢了一个包,整个 TCP 连接都要等待重传,导致复用该连接的所有 HTTP 请求全部被卡住。

HTTP/3 (底层的革命)

为了解决 TCP 的历史包袱,Google 牵头搞出了基于 UDP 的 QUIC 协议。

  • 底层协议替换:抛弃了 TCP,底层改为基于 UDP 的 QUIC 协议。QUIC 在应用层自己实现了拥塞控制和可靠传输。
  • 彻底解决队头阻塞:因为是基于 UDP,各个 Stream 之间完全独立,某个流丢包绝不会影响其他流。
  • 0-RTT 极速握手:将传输层握手和 TLS 加密握手合并。如果曾经连接过,甚至可以带着加密数据直接发起请求(0-RTT),极大地降低了首屏延迟。
  • 连接迁移:TCP 是基于 (源 IP, 端口, 目的 IP, 端口) 四元组的,手机从 WIFI 切换到 4G 时 IP 改变,TCP 必须断开重连。QUIC 是基于独立的 Connection ID 标识的,即使 IP 变了也能保持连接不断,实现无缝切换。

HTTPS (安全协议)

HTTPS = HTTP + SSL/TLS。通过非对称加密交换密钥 + 对称加密传输数据实现安全通信。

TLS 握手过程 (高频手撕题)

  1. Client Hello:客户端发送支持的 TLS 版本、加密算法列表和一个客户端随机数 (Client Random)
  2. Server Hello:服务端确认加密算法,并返回服务器端随机数 (Server Random) 以及数字证书 (含公钥)
  3. 验证证书:客户端验证证书的合法性(通过操作系统内置的 CA 根证书验证数字签名),拿到服务端的公钥
  4. 生成 Pre-Master Secret:客户端生成第三个随机数(Pre-Master Secret),并用服务端的公钥对其进行加密,发给服务端。
  5. 解密得到密钥:服务端用自己的私钥解密,得到第三个随机数。
  6. 生成最终对称密钥:此时客户端和服务端都有了三个随机数,双方通过协商好的算法,生成完全一致的会话密钥 (Session Key)
  7. 安全通信:后续所有数据都用这个“会话密钥”进行对称加密传输(因为对称加密速度快)。

面试追问:用了 HTTPS 就绝对安全了吗?会被抓包吗? HTTPS 可以防止数据在传输过程中被黑客窃听或篡改(防中间人攻击)。 但是,如果用户主动在手机/电脑上安装了抓包工具(如 Charles/Fiddler)的伪造根证书,抓包工具就能充当“合法的中间人”,成功解密 HTTPS 流量。这也是为什么很多 App 还要额外在代码里做“SSL Pinning (证书锁定)”的原因。