前端高频面试题-精选篇-HTTP模块
# 1 HTTP 报文的组成部分
30 秒速记
- 请求报文:请求行(方法 + 路径 + 版本)→ 请求头 → 空行 → 请求体
- 响应报文:状态行(版本 + 状态码 + 原因短语)→ 响应头 → 空行 → 响应体
- 空行是关键分隔符 —— 头部变长,服务端靠它判断"头结束了";头里混入裸换行就能伪造分隔(
HTTP响应拆分攻击) - 头部过大会被网关拒绝(431),最常见的原因是
cookie膨胀 —— 所以静态资源要放无cookie域名 Content-Length和Transfer-Encoding: chunked二选一,流式响应用后者,所以下载进度条算不出百分比- ⚠️
HTTP/2起头部被压成HEADERS帧、body 是DATA帧,不再是纯文本,但四部分的概念划分仍成立
HTTP/1.x 请求报文由请求行、请求头、空行和请求体组成,响应报文对应状态行、响应头、空行和响应体。 空行是头部与正文的关键分隔,因为头部长度不固定;字段中混入裸换行还可能造成 HTTP 响应拆分。工程上要留意头部过大可能触发 431,常见诱因是同域 cookie 膨胀,因此静态资源可使用无 cookie 域名。已知长度用 Content-Length,流式响应通常用 Transfer-Encoding: chunked;到了 HTTP/2,内容改由 HEADERS 和 DATA 帧承载,但概念划分仍成立。
请求报文四部分:
POST /api/order HTTP/1.1 ← 请求行:方法 + 路径 + 协议版本
Host: api.example.com ← 请求头
Content-Type: application/json
Content-Length: 27
← 空行(关键分隔符)
{"id":123,"count":1} ← 请求体
响应报文四部分:
HTTP/1.1 200 OK ← 状态行:协议版本 + 状态码 + 原因短语
Content-Type: application/json ← 响应头
Cache-Control: no-cache
← 空行
{"code":0,"data":{}} ← 响应体
那个空行为什么重要?
因为 HTTP 头部是变长的 —— 服务端读到一个空行才知道"头结束了,后面是 body"。这也是为什么头部字段不能包含裸的换行符,否则就能伪造出一个假的分隔,这类攻击叫 HTTP 响应拆分。
实际工作中会遇到的几个细节:
① 头部太大会被拒绝。 常见于 cookie 膨胀 —— 每个同域请求都会带上全域 cookie,塞多了轻松几 KB,超过网关限制就返回 431 或直接被断开。所以静态资源该放独立的无 cookie 域名。
② 自定义请求头有代价。 跨域时会触发 OPTIONS 预检,等于每个请求变两个往返;中间的 CDN/网关也可能不透传未知的头。能放 body 就别放头里。
③ Content-Length 和分块传输二选一。 知道总长度就用 Content-Length;流式响应(SSE、大文件、AI 逐字输出)用 Transfer-Encoding: chunked,此时没有总长度,所以做下载进度条时算不出百分比。
④ HTTP/2 之后报文结构变了。 起始行和头部被压缩成 HEADERS 帧(用 HPACK 编码),body 变成 DATA 帧,不再是纯文本。所以严格说"报文由文本行组成"只适用于 HTTP/1.x——但概念层面的四部分划分仍然成立。
面试官追问
追问 1联调时有人把请求报文描述成“请求头加请求体”,但抓到的 POST /api/order HTTP/1.1 不属于任何一项;你会怎样纠正?
该行是请求行,包含方法、路径和协议版本,请求报文还包括请求头、空行与请求体。响应侧对应状态行、响应头、空行和响应体;忽略起始行会丢失方法、目标或状态等关键语义。
追问 2网关团队准备把追踪信息全部塞进自定义请求头,页面跨域调用 20 个接口后延迟明显增加;前端应提出什么调整?
先检查这些自定义头是否触发了 OPTIONS 预检,因为跨域请求可能由一次交互变成两次网络往返。非头部必需的数据应考虑放入请求体,并确认 CDN 与网关是否透传;鉴权等必须位于头部的信息不能为省预检随意迁移。
追问 3下载页依赖 Content-Length 显示百分比,后端改成流式返回大文件后进度条一直是未知;这是前端计算错误吗?
不一定是计算错误,流式响应可能使用 Transfer-Encoding: chunked,响应开始时没有可用的总长度。前端此时只能展示已接收量或不确定进度,除非服务端另行可靠提供总大小;伪造百分比会误导用户。
追问 4线上接口偶发 431,请求体只有几十字节,但同域 cookie 已增长到数 KB;你会沿着报文哪一部分排查?
应优先排查请求头,因为 cookie 随同域请求进入头部,超过网关限制时即使请求体很小也可能被拒绝。清理不必要的 cookie,并让静态资源使用无 cookie 域名;调整网关上限只能缓解,不能消除持续膨胀。
追问 5安全评审发现某响应头的值可被用户输入插入裸换行,开发认为浏览器最终只会把它当字符串;风险在哪里?
裸换行可能伪造头部结束位置或额外头字段,破坏依赖空行划分头部与正文的解析边界,并形成响应拆分风险。应拒绝或规范化这类输入,不能只依赖浏览器容错;代理与源站解析差异还会扩大故障面。
追问 6排查 HTTP/2 请求时,同事坚持按 HTTP/1.1 的纯文本行寻找请求行和空行,为什么可能找不到?
HTTP/2 会把起始信息和头部编码进 HEADERS 帧,并用 HPACK 压缩,正文则位于 DATA 帧,因此线上字节不再按纯文本行排列。概念上仍可区分起始信息、头部和正文,但抓包分析必须按帧协议进行。
# 2 常见状态码
30 秒速记
- 五类看首位:
1xx信息、2xx成功、3xx重定向、4xx客户端错、5xx服务端错 —— 排查时先据此分锅 401是"不知道你是谁"(跳登录),403是"知道但没权限"(提示无权限)——混在一起处理会把越权用户反复踢到登录页301永久重定向会被浏览器硬缓存且传递SEO权重;临时跳转必须用302/307,误用清不掉502是上游返回了无效响应(服务挂了),504是上游超时没返回(处理太慢)—— 区分开能直接指方向- 其余常用:
204(无内容)、206(断点续传)、304(协商缓存命中)、429(限流,配Retry-After) - ⚠️ 别用
200 + body.code表达业务失败 —— 监控和网关只看状态码,CDN还会把错误当成功缓存
状态码按首位分为信息、成功、重定向、客户端错误和服务端错误五类,排查时先用这个范围判断问题方向。 最容易混的是 401 与 403:前者表示未认证,应引导登录;后者表示已认证但无权限,应直接提示,否则用户会被反复踢回登录页。重定向中,301 是永久跳转并可能被浏览器硬缓存,临时场景应选 302 或保证方法不变的 307;网关错误里,502 偏向上游响应无效,504 则是上游超时。业务失败也不宜统一返回 200,否则监控、网关和 CDN 可能无法正确识别错误。
五大类,看首位数字就知道谁的问题:
| 类别 | 含义 | 谁的责任 |
|---|---|---|
1xx |
信息性,请求已收到继续处理 | — |
2xx |
成功 | — |
3xx |
重定向 | — |
4xx |
客户端错误 | 前端/调用方 |
5xx |
服务端错误 | 后端 |
这个划分在排查时很实用:看到 4xx 先查自己的请求(参数、鉴权、方法),看到 5xx 直接找后端。
必须记住的这些:
| 码 | 含义 | 实际场景 |
|---|---|---|
200 |
成功 | — |
201 |
已创建 | POST 创建资源后返回,比笼统的 200 语义好 |
204 |
成功但无内容 | DELETE 成功、OPTIONS 预检响应 |
206 |
部分内容 | 断点续传、视频拖动进度条(配 Range 头) |
301 |
永久重定向 | 域名迁移,会传递 SEO 权重,浏览器会硬缓存 |
302/307 |
临时重定向 | 活动页跳转;307 保证不改变请求方法 |
304 |
未修改 | 协商缓存命中,直接用本地副本 |
400 |
请求语法错误 | 参数格式不对 |
401 |
未认证 | 没登录或 token 过期 → 跳登录页 |
403 |
已认证但无权限 | 登录了但角色不够 → 提示无权限,别跳登录 |
404 |
资源不存在 | — |
405 |
方法不允许 | 用 GET 调了只支持 POST 的接口 |
413 |
请求体过大 | 上传超限 |
429 |
请求过于频繁 | 被限流,配合 Retry-After 头做退避重试 |
500 |
服务端内部错误 | — |
502 |
网关收到上游无效响应 | 后端服务挂了或还没起来 |
503 |
服务不可用 | 过载或维护中 |
504 |
网关超时 | 后端处理太慢 |
三组最容易混的:
① 401 vs 403 —— 401 是"你是谁我不知道"(该跳登录),403 是"我知道你是谁但你不能干这个"(该提示无权限)。前端拦截器把两者混在一起处理,会导致越权用户被反复踢到登录页。
② 301 vs 302 —— 301 会被浏览器硬缓存,之后连请求都不发。临时跳转误用 301,活动结束后老用户依然被强制跳走且清不掉,只能换新路径。
③ 502 vs 504 —— 502 是上游返回了无效响应(服务挂了),504 是上游根本没在超时前返回(处理太慢)。区分开能直接告诉后端往哪个方向查。
一个工程上的强建议:不要用 200 + body 里的 code 表示业务失败。监控和网关只看 HTTP 状态码,全是 200 就发现不了故障;CDN 还可能把错误响应当成功缓存下来。正确做法是 HTTP 状态码反映请求本身的结果,业务细分错误码放 body。
