Skip to content

HTTP ​

HTTP 是浏览器面试的核心地带:报文、方法、状态码、头部、缓存、跨域、连接管理、HTTP/2/3、HTTPS 一网打尽。本文聚焦 HTTP 层,TCP/TLS 传输层细节见计算机网络笔记,缓存与跨域的完整展开见浏览器缓存与跨域。

HTTP 报文结构 ​

HTTP 报文由哪几部分组成 ​

  • HTTP 报文分两类:请求报文与响应报文,结构都是三部分:start line(起始行)+ header(首部)+ body(主体)。
  • 起始行与首部之间、首部与主体之间用空行(\r\n\r\n)分隔;首部是 键: 值 的多行文本。
请求报文:
POST /api/login HTTP/1.1        ← 请求行:方法 + 路径 + 版本
Host: www.example.com
Content-Type: application/json
Content-Length: 32

{"username":"tom"}              ← 请求体(可空)

响应报文:
HTTP/1.1 200 OK                 ← 状态行:版本 + 状态码 + 原因短语
Content-Type: application/json
Content-Length: 15

{"code": 0}
请求报文:
POST /api/login HTTP/1.1        ← 请求行:方法 + 路径 + 版本
Host: www.example.com
Content-Type: application/json
Content-Length: 32

{"username":"tom"}              ← 请求体(可空)

响应报文:
HTTP/1.1 200 OK                 ← 状态行:版本 + 状态码 + 原因短语
Content-Type: application/json
Content-Length: 15

{"code": 0}

请求行与状态行分别怎么写 ​

  • 请求行:方法 空格 请求目标 空格 HTTP版本。请求目标通常是路径 + 查询串(/path?a=1),也有绝对 URI(代理场景)与 *(OPTIONS 通配)。
  • 状态行:HTTP版本 空格 状态码 空格 原因短语。原因短语是给人看的,机器只认状态码。
  • 面试常考:状态行第一个数字表示响应类别(1xx~5xx),如 HTTP/1.1 404 Not Found。

Header 与 Body 的注意点 ​

  • Header 每行一个字段,字段名大小写不敏感;同一字段可多行出现(如多个 Set-Cookie)。
  • 请求体与响应体都可能为空:GET 一般无 body;204 响应不允许带 body。
  • Header 体积有软限制(服务器/网关通常限 8KB~64KB),超限会 431;Body 大小由 Content-Length 或分块传输给出。
  • 常见坑:前端用 XMLHttpRequest/fetch 自定义头会触发 CORS 预检(见跨域节);Content-Length 与实际 body 不符会被服务端判为错误请求。

HTTP 请求方法 ​

GET 和 POST 有什么区别 ​

  • 语义:GET 表示「获取资源」(安全、只读);POST 表示「向服务器提交数据、创建/触发处理」。
  • 幂等:GET 幂等(重复请求结果一致);POST 不保证幂等(重复提交可能创建多条订单)。
  • 位置:GET 参数一般放 URL query,会被浏览器历史、日志、Referer 泄漏;POST 参数放 body,相对更隐蔽但不是加密(HTTPS 才加密)。
  • 缓存:GET 默认可被缓存(强缓存/协商缓存);POST 一般不可缓存(除非显式带 freshness 信息)。
  • 长度:URL 长度受浏览器/服务器限制(通常 2KB~8KB);POST body 容量大得多。
  • 面试加分:语义化角度 "GET 用于查询,POST 用于变更",而不是"POST 更安全"。

什么是幂等,哪些方法幂等 ​

  • 幂等(idempotent):同一请求执行一次与执行多次,对服务器资源产生的效果相同(读到的响应可不同,如第二次 404)。
  • 幂等方法:GET、PUT、DELETE、HEAD、OPTIONS、TRACE。
  • 非幂等:POST、PATCH(按定义 PATCH 不保证幂等,但实现上可做到)。
  • 追问点:DELETE 第一次返回 200、第二次返回 404,为什么仍幂等?——因为资源最终状态一致(都是不存在)。

PUT 和 POST、PATCH 怎么区分 ​

方法语义幂等典型场景
POST提交/创建,交给服务器决定位置否新建订单、登录、上传
PUT用请求体整体替换目标资源,URL 由客户端指定是更新 id=1 的用户(全量)
PATCH对资源做部分修改不保证只改用户昵称字段
  • 面试口径:PUT 是"把资源放成这个样子"(全量、幂等);PATCH 是"对资源做增量修补";POST 是"提交处理"。

HEAD 和 OPTIONS 的用途 ​

  • HEAD:与 GET 相同但响应不带 body,用于只取元信息(检查资源是否存在、看 Content-Length、探活)。
  • OPTIONS:询问服务器支持的能力(响应 Allow: GET, POST...);同时也是 CORS 预检请求使用的方法(见跨域节)。
  • 应用:下载前先 HEAD 拿到文件大小做断点续传校验;接口文档自动生成常发 OPTIONS 探测。

什么是 RESTful 风格 ​

  • RESTful 是用 HTTP 语义组织接口的架构风格:资源用名词 URL 表达,操作用 HTTP 方法表达。
  • 口诀:URL 里只有名词、没有动词;动词交给方法。
操作非 REST(反例)RESTful(正例)
查用户GET /getUser?id=1GET /users/1
新建用户POST /createUserPOST /users
改用户POST /updateUserPUT /users/1(全量)/ PATCH /users/1(部分)
删用户GET /deleteUser?id=1DELETE /users/1
  • 补充要点:状态码表达结果(201 创建成功、204 删除成功、409 冲突);用查询参数过滤排序(GET /users?role=admin&page=2);版本化 /v1/users。

HTTP 状态码 ​

状态码分几类 ​

类别含义代表
1xx信息性响应100 Continue、101 Switching Protocols
2xx成功200、201、204、206
3xx重定向301、302、304、307、308
4xx客户端错误400、401、403、404、405、429
5xx服务端错误500、502、503、504

2xx 常见状态码 ​

  • 200 OK:请求成功,body 为结果。
  • 201 Created:创建成功,Location 头指向新资源(POST/PUT 后常见)。
  • 202 Accepted:已受理但异步处理中(消息队列、异步任务常用)。
  • 204 No Content:成功但无 body(DELETE 成功、PUT 局部更新)。
  • 206 Partial Content:范围请求成功(断点续传/视频拖动,配合 Range,见串讲 Q7)。

3xx 重定向:301/302/307/308 的区别 ​

  • 301 Moved Permanently:永久重定向。方法默认从 POST 改成 GET(历史上 GET 化),新地址用 Location 头给出,搜索引擎会更新收录。
  • 302 Found:临时重定向。默认同样 GET 化;语义上"这次先去别处,下次还来问我"。
  • 303 See Other:明确"请用 GET 去 Location 取结果"(POST 提交后跳结果页的标准做法)。
  • 307 Temporary Redirect:临时重定向,保持原方法与原 body(POST 还是 POST)。
  • 308 Permanent Redirect:永久重定向,保持方法(307 的永久版)。
  • 面试常问:301 和 302 默认会把 POST 变 GET(老规范浏览器行为);要保证方法不变必须用 307/308;https→http 跳转、域名换新用 301。

304 是什么、怎么产生 ​

  • 304 Not Modified:协商缓存命中的响应——客户端带了 If-None-Match/If-Modified-Since,服务器判断资源没变,返回 304 且不带 body,浏览器用本地缓存。
  • 与重定向不同:304 不跳转,只是"告诉浏览器继续用缓存"。
  • 完整机制(Last-Modified/ETag 对比、优先级)见浏览器缓存的协商缓存一节。

4xx 客户端错误 ​

  • 400 Bad Request:请求语法/参数不对(缺字段、JSON 解析失败)。
  • 401 Unauthorized:未认证/凭证失效,响应带 WWW-Authenticate 提示如何认证;与 403 的区别是"你还没证明你是谁"。
  • 403 Forbidden:已认证但无权限(或服务器拒绝透露存在性);与 404 常被安全设计故意互换。
  • 404 Not Found:资源不存在(或不想暴露存在)。
  • 405 Method Not Allowed:方法不支持(如只允许 GET 的接口收到 POST),响应应带 Allow 头。
  • 429 Too Many Requests:触发限流,配合 Retry-After 头告知何时重试。
  • 其他备查:408 请求超时、409 冲突(资源状态冲突)、413 请求体过大、415 媒体类型不支持、431 头过大。

5xx 服务端错误:502 与 504 怎么区分 ​

  • 500 Internal Server Error:服务器内部异常(代码抛错、没接住)。
  • 501 Not Implemented:方法未实现。
  • 502 Bad Gateway:网关/代理收到上游的无效响应(上游挂了、连不上、返回乱数据)。
  • 503 Service Unavailable:服务器过载/维护中,配合 Retry-After。
  • 504 Gateway Timeout:网关等上游响应超时(代理在规定时间内没等到上游回包)。
  • 记忆:502 = 上游"回的东西不对/没连上";504 = 上游"回得太慢超时";503 = 我自己的服务暂时不可用。

HTTP 请求头与响应头 ​

Content-Type 与 Accept(内容协商) ​

  • Accept(请求头):客户端能接受的媒体类型与优先级,如 Accept: text/html,application/json;q=0.9,*/*;q=0.8。
  • Content-Type(实体头,请求/响应都有):body 的实际类型,如 application/json、text/html; charset=utf-8、application/x-www-form-urlencoded、multipart/form-data; boundary=...(文件上传)。
  • 配套:Accept-Encoding: gzip, br → 服务器压缩后响应带 Content-Encoding: gzip;Accept-Language → Content-Language。
  • 前端坑:POST JSON 忘记设 Content-Type: application/json,body 会被按表单解析;form-data 与 urlencoded 结构不同,后端取参方式也不同。

Authorization 认证头 ​

  • 请求头 Authorization: Bearer <token>(JWT 常见)或 Authorization: Basic base64(user:pass)。
  • 服务器对未认证请求返回 401 + WWW-Authenticate,提示认证方式。
  • 与 Cookie 的区别:Cookie 由浏览器自动携带,Authorization 由业务代码显式携带(适合前后端分离、跨域)。
  • 响应头 Set-Cookie: name=value; Path=/; HttpOnly; SameSite=Lax; Max-Age=3600 由服务器下发,浏览器存储后,后续同域请求自动带上请求头 Cookie: name=value。
  • 请求头 Cookie 只是键值对串,不含属性;属性只在 Set-Cookie 时声明。
  • 安全属性(HttpOnly/Secure/SameSite)的作用与细节见浏览器缓存与前端安全。

CORS 相关头有哪些 ​

头方向作用
Origin请求声明来源(协议+域名+端口)
Access-Control-Allow-Origin响应允许的源(* 或具体源)
Access-Control-Allow-Methods响应允许的方法(预检应答)
Access-Control-Allow-Headers响应允许的自定义头(预检应答)
Access-Control-Expose-Headers响应允许 JS 读取的响应头白名单
Access-Control-Allow-Credentials响应是否允许携带凭证(Cookie)
Access-Control-Max-Age响应预检结果可缓存秒数

Cache-Control 指令速查 ​

  • 响应指令:public/private(谁能缓存)、max-age=秒(强缓存时长)、no-cache(可用但每次要回源校验=协商)、no-store(禁止一切缓存)、s-maxage(CDN/共享缓存专用)、must-revalidate(过期必须回源)。
  • 请求指令:no-cache(强制回源校验)、no-store、max-age=0(立即过期重新请求)、only-if-cached。
  • 与 Expires(HTTP/1.0,绝对时间,客户端时间不可信)的优先级:Cache-Control 优先。
  • 详细机制与刷新行为(F5/Ctrl+F5)见浏览器缓存。

其他高频头一览 ​

  • Host:目标主机+端口,HTTP/1.1 起必填(一台服务器挂多个域名靠它区分虚拟主机)。
  • User-Agent:客户端标识(浏览器/系统版本)。
  • Referer:来源页面(防盗链、统计);Origin 是 CORS 用的"来源"(不含路径)。
  • Connection:keep-alive / close(HTTP/1.1 默认 keep-alive)。
  • Upgrade + 101:协议升级(WebSocket 握手用)。
  • X-Forwarded-For / X-Real-IP:代理转发后携带的真实客户端 IP(需信任代理才可信)。
  • Range / Content-Range:范围请求(断点续传,见串讲 Q7)。
  • Retry-After:429/503 时告知何时可重试。
  • HTTP 是无状态协议:服务器不记得上一个请求是谁发的,每个请求相互独立。
  • 电商购物车、登录态都需要"认出你",于是用 Cookie 在客户端保存身份标识,每次请求自动捎带,让服务器"有状态"。
属性作用
Domain / Path限定 cookie 在哪些域/路径下携带
Expires / Max-Age过期时间(Max-Age 优先级更高)
HttpOnlyJS 无法读取,防 XSS 窃取
Secure仅 HTTPS 下传输
SameSite=Strict/Lax/None限制跨站携带,防 CSRF(Lax 是浏览器默认)
  • Cookie 单条上限约 4KB、总量有限;会随每次请求自动带上,增大流量,不适合存大对象(见浏览器缓存的存储对比)。

Session 机制与 SessionID ​

  • Session 是服务端的状态:用户登录后,服务器建一条 session 记录并生成唯一 SessionID。
  • SessionID 通过 Set-Cookie(常见名 JSESSIONID)下发给浏览器,之后每次请求带上,服务器凭它找到对应 session。
  • 集群部署问题:session 默认存在单机内存,多机需要 session 共享(粘性会话、Redis 集中存储、或换无状态 Token)。
维度CookieSession
存储位置客户端服务端
容量约 4KB取决于服务端实现(Redis/内存)
安全性明文存客户端,可被篡改/窃取相对安全,但 SessionID 被偷同样危险
性能请求自动携带,占带宽每次查 session 有服务端开销
典型记住偏好、跟踪标识登录态、购物车
  • 引申:如果只放"用户 ID"这类明文,不要在 Cookie 里直接信,要防篡改(签名/只存 SessionID)。

Token / JWT 与 Session 的区别 ​

  • JWT 是无状态的:签名信息(含过期时间、用户标识)放在 token 里,服务器验签即可,不查库/不存 session,天然适合分布式与跨域。
  • 缺点:签发后难以主动失效(黑名单/短有效期+refresh token 补救);token 体积大。
  • 面试结论:单体传统项目用 Session+Cookie 简单可靠;前后端分离/微服务/移动端多用 Token(JWT)。

缓存机制 ​

强缓存与协商缓存一句话区分 ​

  • 强缓存:命中直接用本地缓存,不发请求(200 from memory/disk cache)。
  • 协商缓存:发请求问服务器,服务器说没变 → 304,浏览器用本地缓存;变了 → 200 + 新资源。
  • 两者可共存,强缓存优先;强缓存没命中/过期才走协商。
  • 完整原理(Expires/Cache-Control/Last-Modified/ETag、刷新操作影响)见浏览器缓存,本文不重复展开。

缓存相关头清单 ​

类别请求头响应头
强缓存—Expires(1.0)、Cache-Control: max-age/s-maxage(1.1)
协商-时间If-Modified-SinceLast-Modified
协商-标识If-None-MatchETag
条件-改后取If-Match—
禁止缓存Cache-Control: no-store(请求/响应均可)—
  • 面试高频:ETag 比 Last-Modified 更准(内容变化才变、可解决秒级精度与内容没变但 mtime 变的问题),优先用 ETag。

跨域 CORS ​

什么是同源策略与跨域 ​

  • 同源 = 协议 + 域名 + 端口 三者一致;任一不同即为跨域,浏览器默认拦截跨域请求的响应读取(请求其实可能发出去了)。
  • 跨域是浏览器的安全机制,不是服务器的限制;CORS 是服务端"开白名单"放行的标准方案。
  • 完整方案清单(JSONP/CORS/代理)见跨域。

简单请求与预检请求 ​

  • 简单请求:方法为 GET/HEAD/POST 且仅用 CORS 安全头(Accept、Content-Type 为表单三兄弟等)→ 直接发,响应带 Access-Control-Allow-Origin 即放行。
  • 预检请求(Preflight):方法非简单(PUT/DELETE)、或带自定义头(如 Authorization)、或 Content-Type 为 application/json → 浏览器先发 OPTIONS 预检,服务器回 Access-Control-Allow-* 通过后才发真实请求。
  • 面试题"为什么会有两次请求":就是预检;用 Access-Control-Max-Age 可缓存预检结果减少次数。
  • 前端:fetch 设 credentials: 'include'(XHR 设 withCredentials = true)。
  • 后端:Access-Control-Allow-Origin 不能是 *,必须是具体源,且响应头 Access-Control-Allow-Credentials: true。
  • Cookie 的 SameSite=None; Secure 才能跨站发送,否则会被浏览器拦(Chrome 默认 Lax)。

连接管理:短连接、keep-alive 与队头阻塞 ​

HTTP/1.0 与 HTTP/1.1 的差异 ​

  • HTTP/1.0:每次请求新建 TCP 连接、用完即关(短连接),且请求里无 Host 头(一台机器只能服务一个站点)。
  • HTTP/1.1:默认 keep-alive 长连接(复用 TCP)、必须带 Host 头(虚拟主机)、支持 Range 断点续传、管线化(pipelining)等。
  • HTTP/1.1 默认长连接,Connection: close 可显式关闭;1.0 要长连则发 Connection: keep-alive。

长连接是怎么实现的,有什么好处 ​

  • 长连接让多个 HTTP 请求复用同一条 TCP 连接,省去反复三次握手/慢启动的开销 → 减少延迟、降低服务器资源消耗。
  • 浏览器对同域并发 TCP 连接数有限制(HTTP/1.1 一般 6 条),多出来的请求排队。
  • 服务端通过超时与最大请求数回收空闲长连接(如 Nginx keepalive_timeout)。

什么是队头阻塞(HOL blocking) ​

  • HTTP/1.1 队头阻塞:同一连接上前一个请求的响应没返回,后面的响应就得等(管线化在浏览器基本没启用)。
  • 缓解手段:浏览器开多条 TCP 连接(并行 6 条)、域名分片(把静态资源放多个子域)。
  • 注意:HTTP/1.1 的队头阻塞来自"请求-响应的串行",HTTP/2 解决了它但引入了新的 TCP 层队头阻塞(见下节)。

短连接与长连接怎么选 ​

  • 短连接:请求极少、低频小请求(省连接管理);缺点是每次握手开销大。
  • 长连接:高并发高频请求(同域页面几十个静态资源、API 调用);缺点是占用连接资源、需处理超时/断线重连。
  • 名词辨析:HTTP 长连接(keep-alive)是复用连接;TCP 长连接多指心跳保活(WebSocket 等场景)。

HTTP/2 ​

HTTP/2 解决了什么问题 ​

  • 目标:解决 HTTP/1.1 的队头阻塞与头部冗余两大痛点,同时保持语义兼容(方法/状态码/头字段不变)。
  • 核心手段:二进制分帧 + 多路复用 + 头部压缩 + 服务端推送。
  • 上线前提:HTTPS(主流浏览器要求 HTTP/2 over TLS,ALPN 协商)。

二进制分帧与多路复用 ​

  • HTTP/1.x 报文是纯文本、按顺序解析;HTTP/2 把报文拆成一个个 frame(帧),不同请求的帧交错在同一 TCP 连接上传输,接收方按 stream id 重组。
  • 一个连接上可同时跑多个 stream(流),互不等待 → 真正并行,消除了应用层的队头阻塞。
HTTP/1.1:连接串行 [请求A...响应A][请求B...响应B]
HTTP/2  :一个 TCP 连接里 A、B、C 的帧交错传输
          ── A1 B1 A2 C1 B2 A3 C2 ── (stream id 区分归属)
HTTP/1.1:连接串行 [请求A...响应A][请求B...响应B]
HTTP/2  :一个 TCP 连接里 A、B、C 的帧交错传输
          ── A1 B1 A2 C1 B2 A3 C2 ── (stream id 区分归属)
  • 帧有优先级/依赖设置,可让首屏资源优先到达。

HPACK 头部压缩 ​

  • 请求头重复度高(Cookie、User-Agent 每次都一样)。HPACK 用静态表 + 动态表 + Huffman 编码把重复头压缩。
  • 静态表:61 个常见头(如 :method: GET)用 1 字节索引代替。
  • 动态表:连接内双方各自维护,出现过的头加入表,后续用索引引用。
  • 效果:头部体积通常减少 80% 以上,尤其对小请求收益巨大。

Server Push(服务端推送) ​

  • 服务器预测客户端会请求的资源(如 HTML 里的 CSS/JS),在收到 HTML 请求后主动推送,省去客户端再次请求的往返。
  • 现实情况:需要服务端明确配置;浏览器支持度反复(Chrome 已默认关闭/移除),实践中优先级远低于"预加载"与 HTTP/3,面试了解即可。

HTTP/2 为什么还有队头阻塞 ​

  • HTTP/2 消除了HTTP 层的队头阻塞,但 HTTP/2 依赖 TCP:TCP 保证有序传输,一个包丢失会触发重传并阻塞后续所有数据,即使它们属于不同 stream。
  • 这就是 TCP 层队头阻塞——丢包率高的弱网下,多路复用优势被抵消。
  • 根治方案是 HTTP/3 把传输层换成基于 UDP 的 QUIC(每个 stream 独立可靠传输)。

HTTP/3(QUIC) ​

QUIC 为什么基于 UDP 还可靠 ​

  • HTTP/3 的传输层是 QUIC,跑在 UDP 之上,把"可靠传输、拥塞控制、加密、多路复用"全部在用户态实现。
  • QUIC 内部给每个 stream 独立做可靠性与流量控制:一个 stream 丢包只重传该 stream,不影响其他 stream → 彻底消除 TCP 层队头阻塞。
  • 连接建立更快:QUIC 握手合并了传输握手与 TLS 1.3 握手。

0-RTT 与连接迁移 ​

  • 0-RTT:与服务器通信过的客户端,重连时可携带上次协商的密钥直接发数据,省掉整个握手往返(有重放风险,用于安全要求不高的场景)。
  • 1-RTT:首次连接需要一次往返完成握手(QUIC + TLS 1.3)。
  • 连接迁移:连接用 Connection ID 标识而非四元组(IP+端口),手机切 WiFi/4G 时 IP 变了连接不断,不需要重连。
  • 面试口径:HTTP/3 = HTTP 语义 + QUIC(UDP + TLS1.3 + 多路复用 + 0-RTT + 连接迁移)。

HTTP/3 的现状与问题 ​

  • 优势场景:弱网、移动网络、高丢包环境改善明显。
  • 现实问题:UDP 在部分企业网络/中间设备被限速或封锁;服务端与 CDN 支持仍在普及;CPU 开销高于 TCP。
  • 演进结论话术:HTTP/1.1(文本、串行)→ HTTP/2(二进制、多路复用,仍受 TCP 队头阻塞)→ HTTP/3(UDP+QUIC,解决传输层队头阻塞)。

HTTPS(HTTP 层视角) ​

HTTP 与 HTTPS 的区别 ​

  • HTTPS = HTTP + TLS/SSL:在 HTTP 与 TCP 之间加了一层 TLS,提供加密、完整性校验、身份认证。
  • 默认端口:HTTP 80、HTTPS 443。
  • 防窃听(明文变密文)、防篡改(MAC 校验)、防冒充(证书验身份);TLS 记录层的细节在计算机网络笔记。

TLS 握手流程(简要版) ​

  • 一次典型握手(TLS 1.2,RSA/ECDHE 类):
    1. ClientHello:客户端发随机数、支持的加密套件列表。
    2. ServerHello:服务器选定套件、回自己的随机数;下发证书链。
    3. 客户端验证证书(链到受信根 CA),用证书公钥完成密钥交换(如 ECDHE 参数或加密预主密钥)。
    4. 双方各自算出会话密钥(对称密钥),互相发 Finished 确认。
    5. 之后应用数据用会话密钥对称加密传输。
  • 简化记忆:非对称/证书完成"身份认证+密钥协商",对称加密承载"实际数据"。
  • TLS 1.3:握手缩到 1-RTT,去掉弱套件,支持 0-RTT 恢复。

对称加密 + 非对称加密怎么配合 ​

  • 对称加密(AES 等):快,但密钥怎么安全地给到对方是难题。
  • 非对称加密(RSA/ECDHE):公钥加密私钥解密,可安全交换,但慢、密文大。
  • 配合:用非对称/密钥交换算法协商出一个临时会话密钥,之后全程用对称加密传输 → 兼顾安全与性能(混合加密)。

证书链与 CA 的作用 ​

  • 服务器证书由 CA(证书颁发机构) 签发;证书里含域名、公钥、有效期、CA 签名。
  • 证书链:服务器证书 ← 中间 CA 证书 ← 根 CA 证书,浏览器内置受信根证书库,逐级验证签名直到信任的根。
  • 校验点:域名匹配(SAN)、有效期、链完整、是否被吊销(OCSP)。
  • 自签名证书不会被浏览器信任,会报警告——这就是本地 https 调试常见的坑。

中间人攻击与防范 ​

  • 中间人(MITM):攻击者插在客户端与服务器之间,各自伪装成对方,解密/篡改流量。
  • HTTPS 防 MITM 的关键是证书验证:客户端校验证书不是真的(自签名/域名不符/CA 不受信)时就应拒绝连接。
  • 防范:不点"继续访问"绕过警告;企业/抓包工具装的根证书本质上就是"被信任的中间人";服务端开启 HSTS 强制 HTTPS、证书固定(pinning)用于高安全场景。
  • 与前端安全的关系:XSS/CSRF 是应用层攻击,HTTPS 管的是传输链路安全,两者互补。

高频面试 Q&A 串讲(15 题) ​

Q1:输入 URL 到页面展示,HTTP 部分发生了什么 ​

  • 解析 URL → DNS 解析域名拿 IP → 建立 TCP 连接(三次握手)→ HTTPS 则先 TLS 握手 → 发 HTTP 请求(请求行+头+body)→ 服务器返回响应(状态行+头+body)→ 浏览器解析 HTML,期间并发请求 CSS/JS/图片(走缓存或网络)→ 页面渲染。
  • 浏览器里看到的往往是一串请求而不是一个:主文档 + 静态资源各自是一次 HTTP 事务。
  • 关联阅读:页面加载执行(渲染侧)、计算机网络笔记(TCP/DNS 细节)。

Q2:GET 与 POST 的完整区别 ​

  • 语义:GET 取资源、POST 提交变更;GET 幂等可缓存、POST 不保证。
  • 载体:GET 参数在 URL(有长度限制、会进日志/历史记录),POST 参数在 body(容量大)。
  • 安全:两者明文等价,都不安全;敏感数据必须靠 HTTPS,而不是靠 POST。
  • 缓存与回退:GET 可被浏览器缓存、可刷新重放;POST 默认不缓存,重复提交要防重。
  • 详见上文"HTTP 请求方法"一节。

Q3:304 是怎么产生的,与强缓存什么关系 ​

  • 流程:资源上次响应带 ETag/Last-Modified 且缓存策略允许 → 本次请求带 If-None-Match/If-Modified-Since → 服务器比对未变化 → 返回 304 + 空 body → 浏览器用本地缓存。
  • 关系:强缓存命中(Cache-Control: max-age 内)根本不发请求;发请求还返回 304 说明强缓存已过期、走的是协商缓存。
  • 刷 F5 与 Ctrl+F5 对两者的影响见浏览器缓存。

Q4:长连接与短连接的区别和应用 ​

  • 短连接:一来一回就关 TCP(HTTP/1.0 默认),简单但握手开销大。
  • 长连接:复用连接处理多个请求(HTTP/1.1 默认 keep-alive),省握手、可做管线化。
  • 应用:Web 页面资源密集用长连接;低频接口/需要及时释放资源的场景考虑短连接;服务端要设超时防止连接泄漏。

Q5:HTTP/1.1、HTTP/2、HTTP/3 演进对比 ​

维度HTTP/1.1HTTP/2HTTP/3
传输文本二进制分帧二进制(QUIC)
底层TCPTCPUDP + QUIC
连接复用串行(多 TCP)多路复用单连接多路复用单连接
队头阻塞有(应用层)传输层仍有(TCP)基本消除
头部压缩无HPACKQPACK
握手多次往返TLS 一般 1-2 RTT0/1-RTT
其他Host 头/RangeServer Push连接迁移

Q6:HTTP/2 多路复用为什么还有队头阻塞 ​

  • 多路复用解决的是"请求在应用层排队";但所有 stream 共享一条 TCP,TCP 必须按序交付。
  • 一旦底层丢包,TCP 重传期间后续数据全部卡住 → 不同 stream 互相拖累。
  • 一句话:队头阻塞从 HTTP 层转移到了 TCP 层,丢包率越高影响越大。

Q7:断点续传 / 分块上传怎么实现 ​

  • 下载续传:请求头 Range: bytes=1024-(从 1024 字节开始),服务器支持则返回 206 Partial Content + Content-Range: bytes 1024-2047/2048,不支持就回 200 全量。
  • 条件续传:带 If-Range: <etag>,资源没变才给 206,变了给 200 重新下。
  • 上传分块:客户端把文件切片逐个上传,服务端记录每片偏移,最后合并;或用 multipart 多段;断点续传思路相同(记录已传偏移)。
  • 应用:下载工具断点续传、大文件秒传(先传 hash 判重)。

Q8:SSE 与 WebSocket 的区别 ​

维度SSE(Server-Sent Events)WebSocket
方向服务器 → 客户端单向全双工
协议普通 HTTP(text/event-stream)独立协议(HTTP Upgrade 101 握手后)
自动重连自带(EventSource 自动重连+断点续传 id)需自己实现
消息格式文本文本/二进制
适用服务端推送:通知、股票、日志流聊天、游戏、双向实时交互
  • 一句话:只要"服务器单向下发"(通知、feed),优先 SSE——基于 HTTP 简单、能过代理、自动重连;需要双向实时通信才上 WebSocket。

Q9:为什么需要 Content-Type 与 Accept,什么时候会有两次请求 ​

  • Accept 声明"我能接受什么",Content-Type 声明"这个 body 是什么"——两者配合完成内容协商(格式、压缩、语言)。
  • 两次请求 = CORS 预检:非简单请求(自定义头、JSON、PUT/DELETE)先发 OPTIONS,通过后再发真实请求;可用 Access-Control-Max-Age 缓存预检。
  • 详见上文 CORS 节与跨域。

Q10:HTTP 无状态,登录态怎么保持 ​

  • 方案一 Session+Cookie:登录后服务端记 session,SessionID 下到 Cookie,请求自动携带。
  • 方案二 Token(JWT):登录后发签名 token,客户端存起来(localStorage/内存),请求头带 Authorization: Bearer xxx。
  • 方案三(简单场景)签名 Cookie 直接存用户标识。
  • 横向扩展:Session 需集中存储(Redis),Token 天然适合分布式;见上文 Cookie 与 Session 节。

Q11:代理转发后怎么拿真实 IP ​

  • 请求经过 Nginx/CDN 等反向代理,服务端看到的源 IP 是代理的。
  • 代理把真实 IP 追加到 X-Forwarded-For(每经过一跳追加一个)或 X-Real-IP(Nginx 常见)。
  • 注意:这些头客户端可伪造,只有可信代理设置/覆盖时才可信;取"最左的第一个不可信段"要结合代理链配置判断。

Q12:chunked 分块传输是干什么的 ​

  • Transfer-Encoding: chunked:响应体长度未知时(如流式输出、动态生成大文件),边生成边按"长度+块数据"发送,最后发一个 0 长度块结束。
  • 与 Content-Length 互斥:有 chunked 就不写 Content-Length。
  • 应用:SSE、大文件流式下载、服务端渲染流式输出;面试答"动态内容、长度未知、流式传输"即命中。

Q13:OPTIONS 预检在哪些场景出现 ​

  • 方法不是 GET/HEAD/POST;或 POST 的 Content-Type 不是表单三类;或带了自定义请求头(Authorization、X-Token);或请求带非简单头的 cookie 凭证场景。
  • 出现两次请求先别慌:预检 200 只是"放行",看真实请求是否成功。
  • 优化:合并请求头(少自定义头)、服务端配 Access-Control-Max-Age 缓存预检。

Q14:CDN 缓存与浏览器缓存怎么配合 ​

  • CDN 是"中间层缓存":用户请求先打到 CDN 边缘节点,命中则直接返回,未命中才回源站。
  • 控制头分两层:Cache-Control: max-age 管浏览器/本地;s-maxage/public 管 CDN/共享缓存;no-cache 让 CDN 每次回源校验。
  • 版本号/文件名 hash(指纹)更新时,浏览器与 CDN 缓存一起失效 → 前端构建的静态资源更新策略。
  • 详见浏览器缓存的缓存场景与静态资源指纹。

Q15:HTTPS 全流程一句话串讲 ​

  • 客户端连服务器 → TCP 三次握手 → TLS 握手(校验证书链确认身份 + 协商会话密钥)→ 之后 HTTP 报文用会话密钥对称加密传输 → 结束用四次挥手断开。
  • 安全三件套:加密(防窃听)、完整性(防篡改)、认证(防冒充)。
  • 密钥交换与握手细节、证书校验、中间人的关系见上文 HTTPS 一节与计算机网络笔记。