定义
页面跳转(Page Redirect)是Web服务通过HTTP状态码通知客户端当前请求的资源已移动到其他URL的机制。HTTP协议将3xx状态码定义为重定向类别,其中301 Moved Permanently、302 Found、303 See Other、307 Temporary Redirect、308 Permanent Redirect是最常用的五种。跳转的完整语义由三部分组成:状态码本身、Location响应头中携带的目标URL、以及缓存策略字段(Cache-Control、Expires)。状态码决定了跳转的类型与持久性,Location指定跳转去向,而缓存字段决定浏览器与CDN是否在后续请求中直接复用跳转结果而不回源。
在浏览器中,一次页面跳转的执行链路是:客户端请求原始URL → 服务器返回3xx状态码与Location → 浏览器解析Location并发起第二次请求 → 最终渲染目标页面。该过程中,状态码的语义差异会让浏览器采用不同的缓存策略:永久类跳转(301/308)默认被长期缓存,临时类跳转(302/307)仅在服务器明确下发缓存头时才被缓存。
工作原理
状态码语义与Location头
RFC 9110将301、302、307、308定义为重定向状态码。301表示资源已永久移动,旧URL应退出索引,搜索引擎将页面权重传递给新URL。302表示资源临时位于其他URL,旧URL仍然有效,搜索引擎继续抓取与索引旧URL。303 See Other用于将POST请求结果重定向到GET资源,避免刷新页面时重复提交表单。307与302语义一致,区别在于307要求客户端必须保持原始请求方法(POST必须继续用POST),而302在HTTP/1.1规范与浏览器实践中常被改写为GET。308与301同理,但强制保持请求方法与请求体不变。
Location头是重定向响应的必选字段,其值为绝对URL或相对URL。Nginx与Apache在生成3xx响应时,会将原始请求的Host头与Location值拼接,形成完整跳转地址。对于CDN而言,Location头还会被改写挂载在缓存节点上,节点下一次收到相同请求时,可直接返回缓存的重定向响应,无需回源。
浏览器缓存决策链路
浏览器并不总是机械地执行3xx跳转。Chrome、Firefox与Safari对永久重定向(301/308)的内置策略是“默认缓存”:即使响应中未携带Cache-Control字段,浏览器仍会在本地缓存中写入一条重定向记录,有效期为浏览器计算出的启发式时间(通常为原始请求响应时间的10%)。而临时重定向(302/307)默认不被缓存,浏览器每次请求都会重新访问服务器。
当响应头中出现Cache-Control字段时,决策优先级会变化。三种典型组合如下:
- Cache-Control: max-age=86400 配合302状态码,浏览器会缓存该跳转24小时,期间不再发起真实请求。
- Cache-Control: no-store 配合301状态码,浏览器按协议不得缓存该跳转,每次请求都回源确认。
- Expires字段在HTTP/1.1中被Cache-Control取代,但仍在兼容旧客户端时生效。
在HTTPS场景中,浏览器还会额外检查HSTS策略与证书有效性。Chrome 108以上版本已将主框架请求的301/308跳转视为重点缓存对象,而fetch/XHR请求的跳转缓存从Chrome 62起也已支持302的启发式缓存。
CDN与中间层缓存行为
CDN节点对3xx响应采用与浏览器不同的缓存语义。按照RFC 9111,CDN(共享缓存)只缓存被显式标记为可缓存的响应,除非配置了强制缓存策略。实际生产环境中,主流CDN厂商对301/302的处理分为两种模式:默认模式在无Cache-Control字段时,对301缓存固定时间(Cloudflare缓存24小时,阿里云默认缓存10分钟),对302不缓存;自定义模式则完全遵循源站Cache-Control头。为控制跳转链路延迟,大型站点会在源站的Nginx层为301响应增加Cache-Control: max-age=86400,并为302增加Cache-Control: no-cache,让CDN节点与浏览器协同工作。
技术分类
按状态码类型划分
- 永久类重定向:301(方法可改写)、308(方法不可改写)。适用于域名变更、URL规范化、HTTP跳HTTPS等长期性变更。
- 临时类重定向: 302(方法可改写)、307(方法不可改写)、303(强制转换为GET)。适用于A/B测试、活动页轮播、移动端UA适配等短期或动态场景。
按实现层级划分
- 服务器端脚本跳转:在PHP/Python/Java代码中调用header()或redirect()函数,由应用程序动态控制跳转目标,可依据User-Agent、Cookie、IP等参数实时决策。
- 网页服务器层跳转: Nginx的return 301与rewrite规则、Apache的Redirect与RewriteRule指令,在Web层直接完成跳转,性能最高且不消耗应用服务器资源。
- 边缘网络跳转: 在CDN或边缘计算节点上利用Edge Function改写Location头,将跳转决策下沉至离用户最近的节点,TTFB可控制在50ms以内。
- 客户端跳转: 通过meta refresh或JavaScript,在页面加载后延迟执行跳转。此类方式不返回3xx状态码,搜索引擎识别准确度低,只适合无需SEO的业务场景。
应用场景
页面跳转在Web技术栈中承担三类核心角色:资源迁移、流量分发与用户设备适配。
第一类是站点整体迁移与HTTPS化。将域名从example.com迁移至newexample.com时,在旧域名所有路径上配置301响应,并在响应头中写入Cache-Control: max-age=86400,浏览器与搜索引擎会用最短时间完成权重转移。根据Google Search Central的实测,全站301迁移的中位数周期为3到6周。
第二类是URL规范化。将www与non-www站点、带尾斜杠与不带尾斜杠的路径统一到单一版本,通过308或301收敛权重,避免搜索引擎将多个URL视为重复内容。
第三类是AB页跳转与Cloak场景。ABcloakPro斗篷等AB页跳转服务在页面跳转层利用状态码语义与缓存行为,将真实投放页与审核页通过动态301/302分流到不同用户群的访问路径上。例如对同一URL,正常用户与非正常用户的差异决策通过边缘网络层301跳转完成,跳转速度直接决定用户流失率与审核通过率。这类场景对状态码的精确选择极其敏感:永久性白名单用户应使用301配长缓存,降低重复校验成本;临时性可疑用户则使用302配no-cache,确保每次请求都执行最新风控规则。
与相邻概念对比
页面跳转常与Cloak技术、反向代理、DNS解析被混为一谈,三者在技术栈上处于不同层级。
页面跳转(HTTP重定向)作用于应用层,返回3xx响应并让客户端重新发起请求;反向代理在传输层与应用层之间转发请求,服务器返回的内容由代理服务器直接透传,客户端感知不到变化;DNS解析则作用于域名解析层,通过修改A/AAAA记录或CNAME将访客导向不同IP。
与Cloak技术的关系上,页面跳转是斗篷系统的一个关键执行组件,而非斗篷本身。Cloak技术的核心是访客识别算法(设备指纹、User-Agent过滤、IP段策略),跳转只是将识别结果落地为实际路由动作。相比之下,302跳转更适合动态斗篷规则,因为其非缓存属性可以实时生效;301跳转则适合长期的白名单静态分流。
另外,301与302并非简单的“永久”与“临时”之别。在浏览器实践中,301的缓存行为可由Cache-Control: no-store完全抑制;302在特定条件下也能被主动缓存。SEO行业中“301传权、302不传权”的说法,本质上描述的不是权重传递差异,而是搜索引擎爬虫对永久与临时跳转的缓存策略差异。
常见问题
301跳转一定会被浏览器永久缓存吗?
不是。RFC 9111允许源站通过Cache-Control: no-store或Cache-Control: max-age=0禁止缓存重定向结果。浏览器优先遵循显式缓存指令,而非状态码本身。只有未携带缓存头时,浏览器才采用启发式缓存策略。
302跳转在什么条件下会被浏览器缓存?
当服务器在302响应中明确返回Cache-Control或Expires字段时,浏览器会将其视为可复用缓存项。例如返回302与Cache-Control: max-age=3600时,浏览器在1小时内不会回源。这也是很多AB页跳转服务用302做动态路由时,会顺手写上no-cache的原因。
为什么Cloak系统偏爱302而不是307?
原因有二。302将方法自动改写为GET的特性,简化了从POST请求跳转到静态审核页的处理逻辑;而307严格保持方法与请求体,在风控场景中易导致请求体泄露或异常延迟。同时,302也降低了搜索引擎对跳转目标的可信度,所以需要配合页面级别的内容指纹做策略平衡,避免被识别为桥页(Doorway Page)。
缓存头no-cache与no-store的区别是什么?
no-cache表示可以缓存但使用前必须回源验证(向服务器确认资源是否变化),no-store表示不允许缓存响应内容。对于页面跳转场景,no-cache能保留ETag条件请求带来的校验效率,而no-store则彻底取消缓存。严谨的斗篷系统在302跳转响应中一般使用no-cache,而不是no-store,以保留条件请求带来的性能优化。