301还是302?小心无限重定向循环:http_study完整实测HTTP重定向
2026/8/22 14:57:18 网站建设 项目流程

301还是302?小心无限重定向循环:http_study完整实测HTTP重定向

【免费下载链接】http_studyfollow me to study http项目地址: https://gitcode.com/gh_mirrors/ht/http_study

HTTP重定向是Web世界里最常用也最容易踩坑的机制之一。本文基于开源项目http_study(一个用 OpenResty 手把手带你学 HTTP 协议的实战练习库),通过 302 临时重定向、301 永久重定向和无限重定向循环 3 个真实实验,带你完整实测 HTTP 重定向的全过程,并附上可直接复现的实验环境搭建步骤。🎯

301和302的区别,一张表看懂

在动手之前,先记住这张核心对照表:

对比项301 永久重定向302 临时重定向
含义资源"搬家"了,新地址是最终地址资源"临时搬走",下次还来老地址
浏览器行为更新书签,后续直接请求新地址每次仍请求老地址,跟着 Location 跳转
缓存风险⚠️ 可能被客户端/中间缓存长期记住一般不缓存
典型场景域名迁移、http 跳 https、去掉 www登录跳转、活动页过渡

一句话记忆:301 是"永久通知",302 是"临时改道"。选错了,最轻的是用户体验变差,最重的就是下面的无限重定向循环。

3步搭好HTTP重定向实验环境

http_study 项目内置了全套重定向实验脚本(第 18 课),跟着下面 3 步就能跑起来:

第 1 步:获取项目

git clone https://gitcode.com/gh_mirrors/ht/http_study

第 2 步:绑定测试域名

把项目根目录下的hosts文件内容追加到系统 hosts 文件。它把 3 个测试域名指向本机:

  • www.chrono.com→ 127.0.0.1(HTTP 服务)
  • www.metroid.net→ 127.0.0.1(HTTPS 服务)
  • origin.io→ 127.0.0.1(模拟源站)

第 3 步:启动 OpenResty

进入www目录执行:

cd www ./run.sh start

启动脚本www/run.sh会以项目自带的www/conf/nginx.conf配置启动 OpenResty。想省事也可以用 Docker 一键跑:docker pull chronolaw/http_study后按仓库说明运行即可。

💡 所有NN-N.lua脚本都通过www/conf/http/servers/locations.inc中的正则 location 自动挂载——访问/18-1就会执行www/lua/18-1.lua,无需额外配置。

实测1:302临时重定向,看Location怎么工作

访问/18-1接口,它接受两个参数:

  • dst:重定向目标地址
  • code:状态码,301 或 302(默认 302)

实现逻辑在 www/lua/18-1.lua 中,核心就一行ngx.redirect(new_uri, code)。用 curl 只看响应头来验证:

curl -I "http://127.0.0.1/18-1?dst=/index.html&code=302"

你会看到类似这样的响应:

HTTP/1.1 302 Found Location: /index.html Referer: /18-1?dst=%2Findex.html&code=302

三个关键点:

  1. 状态行是 302:告诉客户端"临时搬走";
  2. Location 头:客户端必须依据它发起新请求,这是重定向的核心字段;
  3. Referer 头:脚本还特意回写了一个自定义 Referer,记录"我是从哪被跳转过来的",这在排查跳转链路上非常好用。

实测2:301永久重定向,和302有何不同

只需把code参数换成 301:

curl -I "http://127.0.0.1/18-1?dst=https://www.metroid.net/&code=301"

响应变为:

HTTP/1.1 301 Moved Permanently Location: https://www.metroid.net/

⚠️重点来了:301 的 Location 指向一个 HTTPS 地址。如果你在浏览器里访问过一次,浏览器可能"记住"这个映射,之后直接跳过 301 源地址。这在正式迁移中是特性,但在调试期就是噩梦——你以为改了规则没生效,其实浏览器根本没再问你。调试重定向问题,永远先清缓存或用无痕窗口。

实测3:亲手复现无限重定向循环

这是本课最刺激的部分。项目里的 www/lua/18-2.lua 就两行核心代码,注释写得很直白:"test for infinite loop redirection":

  • /18-2返回 302,Location 指向/18-1?dst=18-2
  • /18-1解出dst=18-2,再返回 302,Location 又指回/18-2

一个 A→B→A→B 的死循环就此形成。用 curl 实测:

curl -v "http://127.0.0.1/18-2"

curl 会打印一连串Location: /18-1?dst=18-2Location: /18-2,直到达到内置上限报错:

curl: (47) Maximum (50) redirects followed

换成浏览器访问http://www.chrono.com/18-2,Chrome 会直接罢工,显示"ERR_TOO_MANY_REDIRECTS"(重定向次数过多)错误页——这就是无数生产事故现场的真实模样。

为什么会循环?避免重定向踩坑的3个技巧

回到代码看本质:/18-1?dst=18-2把跳转目标做成了"参数回显",而目标本身又会跳回来。只要两条重定向规则互指,循环必现。生产环境常见诱因:

  1. 规则互指:nginx 里一条规则把 A 跳到 B,另一条又把 B 跳回 A(本实验就是教科书级案例);
  2. 协议/端口跳来跳去:http 跳 https,而 https 的配置又因为 Host 不匹配把请求跳回 http(项目里www/conf/http/servers/http2.conf中的return 301 https://$host:8443$request_uri;就是标准的 http→https 写法,注意保证反向规则不存在);
  3. 301 被缓存放大:一条写错的 301 被浏览器、CDN、代理层层缓存,改完配置后"迟迟不生效",排查起来极为痛苦。

避坑清单

  • 配置新跳转规则前,先用curl -I走一遍完整跳转链;
  • 排查时用curl -v观察每一跳的 Location,快速定位环路;
  • 调试期优先用 302,确认无误后再改 301;
  • 生产环境给重定向链加长度上限,防止极端情况拖垮服务。

项目文件导航

  • 301/302 重定向脚本:www/lua/18-1.lua
  • 无限重定向循环脚本:www/lua/18-2.lua
  • 数字编号脚本挂载规则:www/conf/http/servers/locations.inc
  • OpenResty 启动/停止/重载脚本:www/run.sh
  • 测试域名解析文件:hosts
  • Docker 一键运行:docker/docker-compose.yml

写在最后

301 还是 302,不只是一个数字的差别——它决定了浏览器、缓存和搜索引擎如何对待你的跳转规则。http_study 用不到 30 行 Lua 代码,就把重定向的机制、Location 的走向和无限循环的翻车现场全部演示了一遍。动手复现一次,比看十篇文章都管用。🚀

【免费下载链接】http_studyfollow me to study http项目地址: https://gitcode.com/gh_mirrors/ht/http_study

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询