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 Permanentlyvs302 Found:301是永久重定向。浏览器会缓存这个重定向,对 SEO 友好(常用于旧域名迁移)。如果用户把旧 URL 加入书签,浏览器会自动将其更新为新 URL。302是临时重定向。浏览器不会缓存。容易被网络劫持(URL 劫持):因为 302 是临时的,搜索引擎会保留旧 URL 但抓取新内容,黑客可以利用这一点用恶意域名 302 指向合法网站,从而在搜索结果中占位;同时由于不被浏览器缓存,中间人(如运营商)更容易通过拦截并伪造 302 响应来插入广告。常用于未登录拦截跳登录页。书签依然会保留旧的 URL。
304 Not Modified:协商缓存命中!告诉客户端直接使用本地缓存。400 Bad Request:客户端发送的请求有语法错误(比如少传了必填参数,或者 JSON 格式不对),服务端无法理解。401 Unauthorizedvs403 Forbidden:401:你没有登录(没有身份凭证 Token,或者 Token 过期)。403:你登录了,但你的角色(权限)不足以访问该资源。
405 Method Not Allowed:请求方法不被允许。比如接口只支持 POST,你却用 GET 去请求。502 Bad Gatewayvs504 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/json或multipart/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=3600或no-cache。ETag/Last-Modified:用于协商缓存的资源标识符和最后修改时间。Set-Cookie:服务端向客户端设置 Cookie。包含HttpOnly、SameSite、Secure等关键安全属性。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 握手过程 (高频手撕题)
- Client Hello:客户端发送支持的 TLS 版本、加密算法列表和一个客户端随机数 (Client Random)。
- Server Hello:服务端确认加密算法,并返回服务器端随机数 (Server Random) 以及数字证书 (含公钥)。
- 验证证书:客户端验证证书的合法性(通过操作系统内置的 CA 根证书验证数字签名),拿到服务端的公钥。
- 生成 Pre-Master Secret:客户端生成第三个随机数(Pre-Master Secret),并用服务端的公钥对其进行加密,发给服务端。
- 解密得到密钥:服务端用自己的私钥解密,得到第三个随机数。
- 生成最终对称密钥:此时客户端和服务端都有了三个随机数,双方通过协商好的算法,生成完全一致的会话密钥 (Session Key)。
- 安全通信:后续所有数据都用这个“会话密钥”进行对称加密传输(因为对称加密速度快)。
面试追问:用了 HTTPS 就绝对安全了吗?会被抓包吗? HTTPS 可以防止数据在传输过程中被黑客窃听或篡改(防中间人攻击)。 但是,如果用户主动在手机/电脑上安装了抓包工具(如 Charles/Fiddler)的伪造根证书,抓包工具就能充当“合法的中间人”,成功解密 HTTPS 流量。这也是为什么很多 App 还要额外在代码里做“SSL Pinning (证书锁定)”的原因。