前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础进阶

  • 精选模块

    • 精选篇

      • 1 HTML模块
      • 2 CSS模块
      • 3 JS模块
      • 4 ES6模块
      • 5 浏览器模块
      • 6 React模块
      • 7 Vue模块
      • 8 Node模块
      • 9 前端工程相关
      • 10 移动多端开发
      • 11 小程序模块
      • 12 Uniapp模块
      • 13 前端安全模块
      • 14 性能优化相关
      • 15 HTTP模块
        • 1 HTTP 报文的组成部分
        • 2 常见状态码
        • 3 从输入URL到呈现页面过程
        • 4 TCP、UDP相关
        • 5 HTTP2相关
        • 6 https相关
        • 7 WebSocket的实现和应用
        • 8 Token、cookie、Session区别
        • 9 一个图片 url 访问后直接下载怎样实现
        • 10 fetch 发送 2 次请求的原因
        • 11 GET 和 POST 的区别
        • 12 301 和 302 的区别
        • 13 DNS的作用、DNS解析的详细过程,DNS优化原理
        • 14 简单请求和复杂请求
        • 15 Http请求中的keep-alive有了解吗
        • 16 管道机制的作用是什么
        • 17 什么情况下会触发option请求
        • 18 GET可以上传图片吗
        • 19 CDN的作用和原理
        • 20 强缓存命中发生了什么?
        • 21 CORS跨域的原理
        • 22 在深圳的网页上输入百度,是怎么把这个请求发到北京的
        • 23 为什么使用多域名部署?
        • 24 页面10张img,http1是怎样的加载表现?怎样解决的?
        • 25 说一说SSO单点登录
        • 26 说一说OAuth
        • 27 HTTP 中的 301、302、303、307、308 响应状态码
      • 16 常用设计模式
      • 17 框架通识
      • 18 排序算法
      • 19 计算机通识
      • 20 React Native模块
      • 21 桌面端模块
      • 22 Flutter模块
      • 23 Android模块
      • 24 iOS模块
    • 进阶篇

# 1 HTTP 报文的组成部分

30 秒速记

  • 请求报文:请求行(方法 + 路径 + 版本)→ 请求头 → 空行 → 请求体
  • 响应报文:状态行(版本 + 状态码 + 原因短语)→ 响应头 → 空行 → 响应体
  • 空行是头和体的分界;头里混进用户输入的换行符,就能伪造头部,叫响应拆分
  • 头太大会被网关拒(431),大多是 cookie 膨胀,静态资源放无 cookie 域名
  • HTTP/2 起不再是纯文本:头部变 HEADERS 帧(HPACK 压缩),请求行变成 :method、:path 伪头,正文是 DATA 帧

HTTP/1.x 的报文就是四段:起始行、头部、空行、正文,请求和响应结构一样,只是起始行不同。 请求的起始行是方法、路径和版本,响应的是版本、状态码和原因短语。那个空行很关键,头部长度不固定,服务端读到空行才知道头结束了。实际工作里跟报文打交道最多的是头部:cookie 塞多了会触发 431,跨域加自定义头会多一次预检。到了 HTTP/2,报文变成二进制帧,概念还是这几块,但抓包时就看不到一行行的文本了。

请求报文四部分:

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——但概念层面的四部分划分仍然成立。

面试官追问

追问 1POST /api/order HTTP/1.1 这一行属于请求头还是请求体?
参考回答

都不是,这是请求行,里面是方法、路径和协议版本。很多人只记得「头 + 体」,漏了起始行和空行,响应那边对应的是状态行 HTTP/1.1 200 OK。

追问 2请求体才几十字节,接口却偶发返回 431,查哪?
参考回答

查请求头,基本是 cookie 太大。同域所有请求都会带上全部 cookie,埋点、A/B 实验各写几个就能到好几 KB。清理没用的 cookie,静态资源换无 cookie 域名,调网关上限只是缓解。

追问 3给每个接口加了个 X-Trace-Id 请求头,跨域接口明显变慢了,为什么?
参考回答

自定义头会让跨域请求变成非简单请求,每次先发 OPTIONS 预检,等于多一个往返。服务端返回 Access-Control-Max-Age 让预检结果缓存,或者把追踪 ID 放到 URL 参数或请求体里。

追问 4后端改成流式下载后,前端进度条拿不到百分比了,是前端写错了吗?
参考回答

不是。流式响应用 Transfer-Encoding: chunked,开始传的时候没有 Content-Length,前端拿不到总大小。要么后端额外在头里给总大小,要么前端只显示已下载多少。

追问 5HTTP/2 抓包时怎么找不到请求行了?
参考回答

HTTP/2 把请求行拆成了 :method、:path、:scheme、:authority 几个伪头,和普通头一起放进 HEADERS 帧压缩传输。DevTools 里看到的文本是浏览器解码后展示的,线上实际字节是二进制帧。

# 2 常见状态码

30 秒速记

  • 看首位分锅:2xx 成功、3xx 重定向、4xx 请求方有问题、5xx 服务端有问题
  • 401 = 不知道你是谁(去登录),403 = 知道你是谁但没权限(提示无权限);混着处理会把越权用户反复踢到登录页
  • 301 / 308 永久,浏览器会缓存;302 / 307 临时;307 / 308 保证不改请求方法,301 / 302 下 POST 可能被改成 GET
  • 502 = 上游返回了坏响应(服务挂了),504 = 上游超时没回(处理太慢)
  • 常用还有 204 无内容、206 断点续传、304 协商缓存命中、429 限流(看 Retry-After)
  • 别用 200 + body.code 表示失败,监控和网关只认状态码,CDN 还可能把错误缓存下来

状态码先看首位分方向:4xx 先查自己的请求,5xx 找后端。 面试最常追的是三组容易混的:401 和 403,一个是没登录,一个是没权限,前端拦截器要分开处理;301 和 302,永久重定向会被浏览器缓存,临时活动配成 301 之后很难收回;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。

面试官追问

追问 1拦截器里 401 和 403 都跳登录页,普通员工点进管理页就一直在循环,怎么改?
参考回答

401 清 token 跳登录;403 保留登录态,弹「无权限」或跳到 403 页面。用户重新登录也还是没权限,跳登录页解决不了问题。

追问 2活动页临时跳转误配成 301,改回 302 后老用户还是被跳走,为什么?
参考回答

301 默认会被浏览器缓存,很多用户之后根本不发请求,直接本地跳了。服务端改配置管不到他们,只能等缓存过期或者换一个新路径。临时跳转一律用 302 或 307。

追问 3表单 POST 提交后后端返回 302 到另一个接口,结果那边收到的是 GET,怎么回事?
参考回答

历史原因,浏览器遇到 301 / 302 会把 POST 改成 GET 再请求。要保留方法和请求体就用 307(临时)或 308(永久)。

追问 4视频拖进度条时服务端每次都返回 200 全量文件,带宽暴涨,查什么?
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础进阶

  • 精选模块

    • 精选篇

      • 1 HTML模块
      • 2 CSS模块
      • 3 JS模块
      • 4 ES6模块
      • 5 浏览器模块
      • 6 React模块
      • 7 Vue模块
      • 8 Node模块
      • 9 前端工程相关
      • 10 移动多端开发
      • 11 小程序模块
      • 12 Uniapp模块
      • 13 前端安全模块
      • 14 性能优化相关
      • 15 HTTP模块
        • 1 HTTP 报文的组成部分
        • 2 常见状态码
        • 3 从输入URL到呈现页面过程
        • 4 TCP、UDP相关
        • 5 HTTP2相关
        • 6 https相关
        • 7 WebSocket的实现和应用
        • 8 Token、cookie、Session区别
        • 9 一个图片 url 访问后直接下载怎样实现
        • 10 fetch 发送 2 次请求的原因
        • 11 GET 和 POST 的区别
        • 12 301 和 302 的区别
        • 13 DNS的作用、DNS解析的详细过程,DNS优化原理
        • 14 简单请求和复杂请求
        • 15 Http请求中的keep-alive有了解吗
        • 16 管道机制的作用是什么
        • 17 什么情况下会触发option请求
        • 18 GET可以上传图片吗
        • 19 CDN的作用和原理
        • 20 强缓存命中发生了什么?
        • 21 CORS跨域的原理
        • 22 在深圳的网页上输入百度,是怎么把这个请求发到北京的
        • 23 为什么使用多域名部署?
        • 24 页面10张img,http1是怎样的加载表现?怎样解决的?
        • 25 说一说SSO单点登录
        • 26 说一说OAuth
        • 27 HTTP 中的 301、302、303、307、308 响应状态码
      • 16 常用设计模式
      • 17 框架通识
      • 18 排序算法
      • 19 计算机通识
      • 20 React Native模块
      • 21 桌面端模块
      • 22 Flutter模块
      • 23 Android模块
      • 24 iOS模块
    • 进阶篇

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

前端高频面试题-精选篇-HTTP模块

# 1 HTTP 报文的组成部分

30 秒速记

  • 请求报文:请求行(方法 + 路径 + 版本)→ 请求头 → 空行 → 请求体
  • 响应报文:状态行(版本 + 状态码 + 原因短语)→ 响应头 → 空行 → 响应体
  • 空行是头和体的分界;头里混进用户输入的换行符,就能伪造头部,叫响应拆分
  • 头太大会被网关拒(431),大多是 cookie 膨胀,静态资源放无 cookie 域名
  • HTTP/2 起不再是纯文本:头部变 HEADERS 帧(HPACK 压缩),请求行变成 :method、:path 伪头,正文是 DATA 帧

HTTP/1.x 的报文就是四段:起始行、头部、空行、正文,请求和响应结构一样,只是起始行不同。 请求的起始行是方法、路径和版本,响应的是版本、状态码和原因短语。那个空行很关键,头部长度不固定,服务端读到空行才知道头结束了。实际工作里跟报文打交道最多的是头部:cookie 塞多了会触发 431,跨域加自定义头会多一次预检。到了 HTTP/2,报文变成二进制帧,概念还是这几块,但抓包时就看不到一行行的文本了。

▶视频讲解 · HTTP 报文的组成部分配音拆解原理、代码示例与常见误区展开观看
🧪​可交互​动手试试

请求报文四部分:

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——但概念层面的四部分划分仍然成立。

面试官追问

追问 1POST /api/order HTTP/1.1 这一行属于请求头还是请求体?
参考回答

都不是,这是请求行,里面是方法、路径和协议版本。很多人只记得「头 + 体」,漏了起始行和空行,响应那边对应的是状态行 HTTP/1.1 200 OK。

追问 2请求体才几十字节,接口却偶发返回 431,查哪?
参考回答

查请求头,基本是 cookie 太大。同域所有请求都会带上全部 cookie,埋点、A/B 实验各写几个就能到好几 KB。清理没用的 cookie,静态资源换无 cookie 域名,调网关上限只是缓解。

追问 3给每个接口加了个 X-Trace-Id 请求头,跨域接口明显变慢了,为什么?
参考回答

自定义头会让跨域请求变成非简单请求,每次先发 OPTIONS 预检,等于多一个往返。服务端返回 Access-Control-Max-Age 让预检结果缓存,或者把追踪 ID 放到 URL 参数或请求体里。

追问 4后端改成流式下载后,前端进度条拿不到百分比了,是前端写错了吗?
参考回答

不是。流式响应用 Transfer-Encoding: chunked,开始传的时候没有 Content-Length,前端拿不到总大小。要么后端额外在头里给总大小,要么前端只显示已下载多少。

追问 5HTTP/2 抓包时怎么找不到请求行了?
参考回答

HTTP/2 把请求行拆成了 :method、:path、:scheme、:authority 几个伪头,和普通头一起放进 HEADERS 帧压缩传输。DevTools 里看到的文本是浏览器解码后展示的,线上实际字节是二进制帧。

# 2 常见状态码

30 秒速记

  • 看首位分锅:2xx 成功、3xx 重定向、4xx 请求方有问题、5xx 服务端有问题
  • 401 = 不知道你是谁(去登录),403 = 知道你是谁但没权限(提示无权限);混着处理会把越权用户反复踢到登录页
  • 301 / 308 永久,浏览器会缓存;302 / 307 临时;307 / 308 保证不改请求方法,301 / 302 下 POST 可能被改成 GET
  • 502 = 上游返回了坏响应(服务挂了),504 = 上游超时没回(处理太慢)
  • 常用还有 204 无内容、206 断点续传、304 协商缓存命中、429 限流(看 Retry-After)
  • 别用 200 + body.code 表示失败,监控和网关只认状态码,CDN 还可能把错误缓存下来

状态码先看首位分方向:4xx 先查自己的请求,5xx 找后端。 面试最常追的是三组容易混的:401 和 403,一个是没登录,一个是没权限,前端拦截器要分开处理;301 和 302,永久重定向会被浏览器缓存,临时活动配成 301 之后很难收回;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。

面试官追问

追问 1拦截器里 401 和 403 都跳登录页,普通员工点进管理页就一直在循环,怎么改?
参考回答

401 清 token 跳登录;403 保留登录态,弹「无权限」或跳到 403 页面。用户重新登录也还是没权限,跳登录页解决不了问题。

追问 2活动页临时跳转误配成 301,改回 302 后老用户还是被跳走,为什么?
参考回答

301 默认会被浏览器缓存,很多用户之后根本不发请求,直接本地跳了。服务端改配置管不到他们,只能等缓存过期或者换一个新路径。临时跳转一律用 302 或 307。

追问 3表单 POST 提交后后端返回 302 到另一个接口,结果那边收到的是 GET,怎么回事?
参考回答

历史原因,浏览器遇到 301 / 302 会把 POST 改成 GET 再请求。要保留方法和请求体就用 307(临时)或 308(永久)。

追问 4视频拖进度条时服务端每次都返回 200 全量文件,带宽暴涨,查什么?
参考回答

看请求有没有带 Range: bytes=...,服务端有没有返回 206 和 Content-Range。Nginx 托管静态文件默认支持,自己写的文件接口经常漏掉这块。

追问 5限流接口返回 429 后,前端马上重试了 5 次,结果更糟了,怎么改?
参考回答

读 Retry-After 头,按它给的秒数再重试;没有就用指数退避加随机抖动,比如 1s、2s、4s,最多三次。所有客户端同时重试会把服务再打挂一次。

# 3 从输入URL到呈现页面过程

30 秒速记

  • 主线:URL 解析 → 查缓存 → DNS → TCP 握手 →(TLS 握手)→ 发请求 → 收响应 → 渲染 → 连接复用或关闭
  • 浏览器内部分工:浏览器进程管地址栏,网络进程负责缓存和请求,渲染进程负责解析和绘制,进程间走 IPC
  • 响应处理:3xx 读 Location 重新发请求;Content-Type 是下载类型就交给下载管理器;是 HTML 才提交给渲染进程
  • 渲染:HTML → DOM,CSS → CSSOM,合成渲染树 → 布局 → 绘制 → 合成
  • 第二次访问很多步会省掉:DNS 缓存、连接复用、强缓存命中不发请求,瓶颈转到解析和执行

从输入 URL 到页面显示,可以按浏览器的三个进程来讲:浏览器进程接收输入,网络进程查缓存、建连、发请求,渲染进程拿到 HTML 后解析和绘制。 网络进程先查本地缓存,强缓存命中就直接返回;没命中才做 DNS 解析、TCP 和 TLS 握手,然后发请求。收到响应后看状态码,重定向就按 Location 重来一遍;再看 Content-Type,是文件下载导航就到此结束,是 HTML 才通知浏览器进程准备渲染进程。渲染进程确认提交后,地址栏才更新,接着开始解析渲染。

▶视频讲解 · 从输入URL到呈现页面过程配音拆解原理、代码示例与常见误区展开观看
🧪​可交互​动手试试

# 3.1 简洁

  • 浏览器的地址栏输入URL并按下回车;
  • DNS 解析:将域名解析成 IP 地址;
  • TCP 连接:TCP 三次握手;(三次握手的目的:为了防止已经失效的连接请求报文段突然又传送到了服务器端,从而产生错误)
  • 发送 HTTP 请求;
  • 服务器处理请求并返回 HTTP 报文;
  • 浏览器解析渲染页面;
  • 断开连接:TCP 四次挥手

# 3.2 详细

← 14 性能优化相关16 常用设计模式 →

fe