前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

# HTTP的重定向

30 秒速记

  • 重定向 = 服务器回 3xx + Location,浏览器自己再发一次请求,所以一共两个来回
  • 永久还是临时:301/308 永久,302/307 临时,永久的会被浏览器缓存、被搜索引擎改索引
  • 方法变不变:303 强制改成 GET;307/308 保留原方法和请求体;301/302 遇到 POST 浏览器通常会改成 GET
  • 站内跳转写相对路径就行,跳站外必须写完整的 https://...
  • 每多一跳多一个来回,规则写乱了还会出现循环,浏览器会报「重定向次数过多」

重定向就是服务器回一个 3xx 状态码加 Location 头,告诉浏览器「去那个地址重新要」,浏览器会自动再发一次请求。 选状态码我只看两件事:这次搬家是永久还是临时,跳过去之后请求方法能不能变。永久用 301,临时用 302;接口里要保住 POST 和请求体就用 307 或 308;表单提交完跳结果页用 303。它和服务端内部转发不一样,浏览器地址栏会变,而且多一个网络来回,所以链路要尽量短,规则之间也别互相指。

面试官追问

追问 1活动页只想临时跳两周,开发写了 301,活动结束后改了配置用户还是被跳走,为什么?
参考回答

301 会被浏览器缓存,没设 Cache-Control 的话可能一直记着,后面改服务端配置老用户也收不到。临时跳转一律用 302,已经发出去的 301 只能等缓存过期或者让用户清缓存。

追问 2网站换了新域名,旧域名上的搜索流量怎么尽量保住?
参考回答

旧域名全站 301 到新域名的对应路径,/a/b 跳 /a/b,别全扔到首页,搜索引擎会把权重转过去。同时站内链接、sitemap、canonical 都换成新域名,减少一跳。

追问 3用户访问 /account 浏览器报「重定向次数过多」,怎么查?
参考回答

curl -IL --max-redirs 10 https://xx.com/account 把每一跳的状态码和 Location 打出来,基本一眼就能看到 A → B → A。最常见的是 CDN 回源用 http,源站又强制跳 https,或者登录态判断在网关和应用两层不一致。

追问 4前端 axios 请求接口,后端登录过期返回 302 到登录页,前端为什么拦不到?
参考回答

浏览器的 XHR 和 fetch 会自动跟随重定向,前端拿到的是登录页那个 200 的 HTML。接口场景应该返回 401,由前端拦截器自己 location.href = '/login',别用 302。

# 重定向的过程

30 秒速记

  • 重定向 = 两次独立请求:第一次拿到 3xx + Location,浏览器再按 Location 发第二次
  • 用户基本无感,地址栏会变成新地址,DevTools 勾上 Preserve log 才看得到中间那跳
  • Location 是响应头,只有配合 3xx(还有 201)才有意义
  • 相对地址按当前请求的 URL 解析,站内可以用;跳站外必须写全 https://
  • ?dst=nginx.org 会被解析成本站下的路径,变成 https://本站/nginx.org

重定向的秘密全在响应头 Location 上:服务器回 301 或 302,带上新地址,浏览器看到就自动再请求一次。 所以它其实是两次完整的 HTTP 请求,第二次有自己的请求行和请求头,和服务端内部转发是两码事。Location 可以写相对地址,比如 /index.html,浏览器会拿当前地址补全;但跳到别的站必须写全,少了 https:// 就会被当成本站的一个路径。开发时 DevTools 记得勾 Preserve log,不然跳完中间那条请求就被清掉了。

  • 301 是“永久重定向”,302 是“临时重定向”,浏览器收到这两个状态码就会跳转到新的 URI。
  • 那么,它们是怎么做到的呢?难道仅仅用这两个代码就能够实现跳转页面吗
  • “重定向”实际上发送了两次 HTTP 请求,第一个请求返回了 302,然后第二个请求就被重定向到了“/index.html”。但如果不用开发者工具的话,你是完全看不到这个跳转过程的,也就是说,重定向是“用户无感知”的

我们再来看看第一个请求返回的响应报文:

这里出现了一个新的头字段“Location: /index.html”,它就是 301/302 重定向跳转的秘密所在。

“Location”字段属于响应字段,必须出现在响应报文里。但只有配合 301/302 状态码才有意义,它标记了服务器要求重定向的 URI,这里就是要求浏览器跳转到“index.html”。

浏览器收到 301/302 报文,会检查响应头里有没有“Location”。如果有,就从字段值里提取出 URI,发出新的 HTTP 请求,相当于自动替我们点击了这个链接。

在“Location”里的 URI 既可以使用绝对 URI,也可以使用相对 URI。所谓“绝对 URI”,就是完整形式的 URI,包括 scheme、host:port、path 等。所谓“相对 URI”,就是省略了 scheme 和 host:port,只有 path 和 query 部分,是不完整的,但可以从请求上下文里计算得到

注意,在重定向时如果只是在站内跳转,你可以放心地使用相对 URI。但如果要跳转到站外,就必须用绝对 URI。

例如,如果想跳转到 Nginx 官网,就必须在“ nginx.org”前把“http://”都写出来,否则浏览器会按照相对 URI 去理解,得到的就会是一个不存在的 URI“ http://www.chrono.com/nginx.org”

http://www.chrono.com/18-1?dst=nginx.org           # 错误
http://www.chrono.com/18-1?dst=http://nginx.org    # 正确
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1重定向和服务端内部转发有什么区别?
参考回答

重定向是浏览器发了两次请求,地址栏会变;内部转发是服务端自己把请求交给另一个处理器,浏览器只发了一次、地址栏不变,比如 Nginx 的 try_files 或者 proxy_pass。

追问 2res.writeHead(302, { Location: 'google.com' }),浏览器最后跳到了哪?
参考回答

跳到 https://当前域名/google.com。没写协议就是相对地址,浏览器按当前 URL 补全。跳站外要写 https://google.com。

追问 3登录页支持 ?redirect= 参数登录后跳回原页面,有什么安全问题?
参考回答

开放重定向。攻击者发一个 https://你的域名/login?redirect=https://钓鱼站,用户看域名是真的,登录完就被带走了。只允许相对路径,或者对目标做域名白名单校验,注意 //evil.com 这种也要拦住。

追问 4fetch 能拿到重定向之前的那个 302 吗?
参考回答

浏览器里不能。redirect: 'manual' 只会给你一个 type 为 opaqueredirect 的响应,状态码是 0,看不到 Location。Node 18 自带的 fetch 没这个限制,能拿到真实的 302 和头。

追问 5POST 请求收到 302 后,第二次请求还是 POST 吗?
参考回答

浏览器通常会改成 GET 并丢掉请求体,这是历史遗留行为。要保住方法和请求体就用 307 或 308。

# 重定向状态码

30 秒速记

  • 301 永久:浏览器会缓存,搜索引擎更新索引,旧地址的权重转到新地址
  • 302 临时:原地址还有效,浏览器不记,下次照样访问旧地址
  • 303 跳完必须用 GET,经典场景是表单 POST 完跳结果页,防重复提交
  • 307 = 不许改方法的 302,308 = 不许改方法的 301
  • 易错点:301/302 收到 POST 时,浏览器实际会改成 GET 再请求,接口迁移要用 307/308

状态码就按两个维度选:永久还是临时,跳过去请求方法能不能变。 永久搬家用 301,浏览器会缓存,搜索引擎会把旧地址的权重转到新地址;临时跳走用 302,原地址还算数。麻烦在 301 和 302 对 POST 的处理,规范本意是不改方法,但浏览器历史上都改成了 GET,于是补了 303、307、308:303 明说改成 GET,307 和 308 明说不许改。现在这三个码主流浏览器早就支持了,接口迁移放心用 307 或 308。

刚才我把重定向的过程基本讲完了,现在来说一下重定向用到的状态码。

最常见的重定向状态码就是 301 和 302,另外还有几个不太常见的,例如 303、307、308 等。它们最终的效果都差不多,让浏览器跳转到新的 URI,但语义上有一些细微的差别,使用的时候要特别注意。

301俗称“永久重定向”(Moved Permanently),意思是原 URI 已经“永久”性地不存在了,今后的所有请求都必须改用新的 URI。

浏览器看到 301,就知道原来的 URI“过时”了,就会做适当的优化。比如历史记录、更新书签,下次可能就会直接用新的 URI 访问,省去了再次跳转的成本。搜索引擎的爬虫看到 301,也会更新索引库,不再使用老的 URI。

302俗称“临时重定向”(“Moved Temporarily”),意思是原 URI 处于“临时维护”状态,新的 URI 是起“顶包”作用的“临时工”。

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

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
        • 重定向的过程
        • 重定向状态码
        • 重定向的应用场景
        • 重定向的相关问题
        • 小结
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

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

HTTP的重定向|HTTP协议篇

# HTTP的重定向

30 秒速记

  • 重定向 = 服务器回 3xx + Location,浏览器自己再发一次请求,所以一共两个来回
  • 永久还是临时:301/308 永久,302/307 临时,永久的会被浏览器缓存、被搜索引擎改索引
  • 方法变不变:303 强制改成 GET;307/308 保留原方法和请求体;301/302 遇到 POST 浏览器通常会改成 GET
  • 站内跳转写相对路径就行,跳站外必须写完整的 https://...
  • 每多一跳多一个来回,规则写乱了还会出现循环,浏览器会报「重定向次数过多」

重定向就是服务器回一个 3xx 状态码加 Location 头,告诉浏览器「去那个地址重新要」,浏览器会自动再发一次请求。 选状态码我只看两件事:这次搬家是永久还是临时,跳过去之后请求方法能不能变。永久用 301,临时用 302;接口里要保住 POST 和请求体就用 307 或 308;表单提交完跳结果页用 303。它和服务端内部转发不一样,浏览器地址栏会变,而且多一个网络来回,所以链路要尽量短,规则之间也别互相指。

面试官追问

追问 1活动页只想临时跳两周,开发写了 301,活动结束后改了配置用户还是被跳走,为什么?
参考回答

301 会被浏览器缓存,没设 Cache-Control 的话可能一直记着,后面改服务端配置老用户也收不到。临时跳转一律用 302,已经发出去的 301 只能等缓存过期或者让用户清缓存。

追问 2网站换了新域名,旧域名上的搜索流量怎么尽量保住?
参考回答

旧域名全站 301 到新域名的对应路径,/a/b 跳 /a/b,别全扔到首页,搜索引擎会把权重转过去。同时站内链接、sitemap、canonical 都换成新域名,减少一跳。

追问 3用户访问 /account 浏览器报「重定向次数过多」,怎么查?
参考回答

curl -IL --max-redirs 10 https://xx.com/account 把每一跳的状态码和 Location 打出来,基本一眼就能看到 A → B → A。最常见的是 CDN 回源用 http,源站又强制跳 https,或者登录态判断在网关和应用两层不一致。

追问 4前端 axios 请求接口,后端登录过期返回 302 到登录页,前端为什么拦不到?
参考回答

浏览器的 XHR 和 fetch 会自动跟随重定向,前端拿到的是登录页那个 200 的 HTML。接口场景应该返回 401,由前端拦截器自己 location.href = '/login',别用 302。

# 重定向的过程

30 秒速记

  • 重定向 = 两次独立请求:第一次拿到 3xx + Location,浏览器再按 Location 发第二次
  • 用户基本无感,地址栏会变成新地址,DevTools 勾上 Preserve log 才看得到中间那跳
  • Location 是响应头,只有配合 3xx(还有 201)才有意义
  • 相对地址按当前请求的 URL 解析,站内可以用;跳站外必须写全 https://
  • ?dst=nginx.org 会被解析成本站下的路径,变成 https://本站/nginx.org

重定向的秘密全在响应头 Location 上:服务器回 301 或 302,带上新地址,浏览器看到就自动再请求一次。 所以它其实是两次完整的 HTTP 请求,第二次有自己的请求行和请求头,和服务端内部转发是两码事。Location 可以写相对地址,比如 /index.html,浏览器会拿当前地址补全;但跳到别的站必须写全,少了 https:// 就会被当成本站的一个路径。开发时 DevTools 记得勾 Preserve log,不然跳完中间那条请求就被清掉了。

  • 301 是“永久重定向”,302 是“临时重定向”,浏览器收到这两个状态码就会跳转到新的 URI。
  • 那么,它们是怎么做到的呢?难道仅仅用这两个代码就能够实现跳转页面吗
  • “重定向”实际上发送了两次 HTTP 请求,第一个请求返回了 302,然后第二个请求就被重定向到了“/index.html”。但如果不用开发者工具的话,你是完全看不到这个跳转过程的,也就是说,重定向是“用户无感知”的

我们再来看看第一个请求返回的响应报文:

这里出现了一个新的头字段“Location: /index.html”,它就是 301/302 重定向跳转的秘密所在。

“Location”字段属于响应字段,必须出现在响应报文里。但只有配合 301/302 状态码才有意义,它标记了服务器要求重定向的 URI,这里就是要求浏览器跳转到“index.html”。

浏览器收到 301/302 报文,会检查响应头里有没有“Location”。如果有,就从字段值里提取出 URI,发出新的 HTTP 请求,相当于自动替我们点击了这个链接。

在“Location”里的 URI 既可以使用绝对 URI,也可以使用相对 URI。所谓“绝对 URI”,就是完整形式的 URI,包括 scheme、host:port、path 等。所谓“相对 URI”,就是省略了 scheme 和 host:port,只有 path 和 query 部分,是不完整的,但可以从请求上下文里计算得到

注意,在重定向时如果只是在站内跳转,你可以放心地使用相对 URI。但如果要跳转到站外,就必须用绝对 URI。

例如,如果想跳转到 Nginx 官网,就必须在“ nginx.org”前把“http://”都写出来,否则浏览器会按照相对 URI 去理解,得到的就会是一个不存在的 URI“ http://www.chrono.com/nginx.org”

http://www.chrono.com/18-1?dst=nginx.org           # 错误
http://www.chrono.com/18-1?dst=http://nginx.org    # 正确
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1重定向和服务端内部转发有什么区别?
参考回答

重定向是浏览器发了两次请求,地址栏会变;内部转发是服务端自己把请求交给另一个处理器,浏览器只发了一次、地址栏不变,比如 Nginx 的 try_files 或者 proxy_pass。

追问 2res.writeHead(302, { Location: 'google.com' }),浏览器最后跳到了哪?
参考回答

跳到 https://当前域名/google.com。没写协议就是相对地址,浏览器按当前 URL 补全。跳站外要写 https://google.com。

追问 3登录页支持 ?redirect= 参数登录后跳回原页面,有什么安全问题?
参考回答

开放重定向。攻击者发一个 https://你的域名/login?redirect=https://钓鱼站,用户看域名是真的,登录完就被带走了。只允许相对路径,或者对目标做域名白名单校验,注意 //evil.com 这种也要拦住。

追问 4fetch 能拿到重定向之前的那个 302 吗?
参考回答

浏览器里不能。redirect: 'manual' 只会给你一个 type 为 opaqueredirect 的响应,状态码是 0,看不到 Location。Node 18 自带的 fetch 没这个限制,能拿到真实的 302 和头。

追问 5POST 请求收到 302 后,第二次请求还是 POST 吗?
参考回答

浏览器通常会改成 GET 并丢掉请求体,这是历史遗留行为。要保住方法和请求体就用 307 或 308。

# 重定向状态码

30 秒速记

  • 301 永久:浏览器会缓存,搜索引擎更新索引,旧地址的权重转到新地址
  • 302 临时:原地址还有效,浏览器不记,下次照样访问旧地址
  • 303 跳完必须用 GET,经典场景是表单 POST 完跳结果页,防重复提交
  • 307 = 不许改方法的 302,308 = 不许改方法的 301
  • 易错点:301/302 收到 POST 时,浏览器实际会改成 GET 再请求,接口迁移要用 307/308

状态码就按两个维度选:永久还是临时,跳过去请求方法能不能变。 永久搬家用 301,浏览器会缓存,搜索引擎会把旧地址的权重转到新地址;临时跳走用 302,原地址还算数。麻烦在 301 和 302 对 POST 的处理,规范本意是不改方法,但浏览器历史上都改成了 GET,于是补了 303、307、308:303 明说改成 GET,307 和 308 明说不许改。现在这三个码主流浏览器早就支持了,接口迁移放心用 307 或 308。

← HTTP的连接管理HTTP的Cookie机制 →

fe