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三个关键点:
- 状态行是 302:告诉客户端"临时搬走";
- Location 头:客户端必须依据它发起新请求,这是重定向的核心字段;
- 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-2和Location: /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把跳转目标做成了"参数回显",而目标本身又会跳回来。只要两条重定向规则互指,循环必现。生产环境常见诱因:
- 规则互指:nginx 里一条规则把 A 跳到 B,另一条又把 B 跳回 A(本实验就是教科书级案例);
- 协议/端口跳来跳去:http 跳 https,而 https 的配置又因为 Host 不匹配把请求跳回 http(项目里
www/conf/http/servers/http2.conf中的return 301 https://$host:8443$request_uri;就是标准的 http→https 写法,注意保证反向规则不存在); - 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),仅供参考