首页 > 解决方案 > 什么 HTTP 响应状态代码用于随机机会的不相关重定向?

问题描述

我的网站有 1% 的随机机会将访问者重定向到此 YouTube 视频。

服务器当前发送旧的 302,但我希望它具有更好的语义。

我不知道重定向是永久的还是临时的。它是永久性的,因为人们总是有 1% 的机会被重定向,而它是暂时的,因为人们不会每次都被重定向。

当前的 3xx 响应状态代码均不符合我网站的行为。

HTTP 3xx 重定向(来源:维基百科)

301 Moved Permanently
这个和所有未来的请求都应该被定向到给定的 URI。[21]

“这个和所有未来的请求” - 不,不是所有未来的请求。

302 Found(以前“暂时移动”)
告诉客户端查看(浏览到)另一个 url。302 已被 303 和 307 取代。这是行业实践与标准相矛盾的一个例子。HTTP/1.0 规范 (RFC 1945) 要求客户端执行临时重定向(最初的描述短语是“临时移动”),[22] 但流行的浏览器使用 303 See Other 的功能实现了 302。因此,HTTP/1.1 添加了状态码 303 和 307 来区分这两种行为。 [23] 但是,一些 Web 应用程序和框架使用 302 状态代码,就好像它是 303。[24]

这令人困惑。它确实声明“302 已被 303 和 307 取代”,所以我想这已经过时但仍然普遍使用?

303 See Other(从 HTTP/1.1 起)
可以使用 GET 方法在另一个 URI 下找到对请求的响应。当收到响应 POST(或 PUT/DELETE)时,客户端应假定服务器已收到数据,并应向给定 URI 发出新的 GET 请求。 [25]

“可以在另一个 URI 下找到对请求的响应” - Rickroll 不是对原始请求的响应。它与我的网站无关!“当收到 POST(或 PUT/DELETE)的响应时,客户端应假定服务器已收到数据,并应向给定的 URI 发出新的 GET 请求。” 303 描述的最后一句话不适用于我的重定向。

307 临时重定向(从 HTTP/1.1 开始)
在这种情况下,应该使用另一个 URI 重复请求;但是,未来的请求仍应使用原始 URI。与历史上的 302 实现方式不同的是,在重新发出原始请求时,不允许更改请求方法。例如,应该使用另一个 POST 请求重复一个 POST 请求。[30]

“在这种情况下,应使用另一个 URI 重复请求;但是,未来的请求仍应使用原始 URI。” 是的!这就是我的重定向。“...重新发出原始请求时,不允许更改请求方法。例如,应该使用另一个 POST 请求重复一个 POST 请求。” 不幸的是,这不适用于我的重定向。我的网站随机 Rickrolls 用户,即使他们提交表单(POST 方法)。

308 永久重定向 (RFC 7538)
应使用另一个 URI 重复请求和所有未来的请求。307 和 308 与 302 和 301 的行为平行,但不允许更改 HTTP 方法。因此,例如,将表单提交到永久重定向的资源可能会顺利进行。 [31]

308 与 301 具有相同的问题,因为并非所有未来的请求都应该转到 Rickroll 视频。此外,不允许更改方法。

我的服务器应该为与我的实际站点无关的随机机会重定向发送什么 HTTP 响应状态代码?

标签: httpredirectserverhttp-status-codeshttp-redirect

解决方案


HTTP 响应状态代码的官方来源是RFC7231,而不是 Wikipedia。您应该仔细阅读RFC7231 第 6.4 节以了解 3XX 状态代码的解释。

“随机重定向访问者”的事情与实际重定向无关,因此符合您要求的状态代码是 303,这在第 6.4.4 节中解释如下(强调我的):

303(参见其他)状态码表示服务器正在将用户代理重定向到不同的资源,如 Location 标头字段中的 URI 所示,旨在提供对原始请求的间接响应。用户代理可以执行针对该 URI 的检索请求(如果使用 HTTP,则为 GET 或 HEAD 请求),该请求也可能被重定向,并将最终结果作为原始请求的答案呈现。请注意,Location 标头字段中的新 URI不被视为等效于有效请求 URI。

303 符合您的要求有三个原因:

  1. “到不同的资源”:您的访问者被重定向到的资源与他们最初请求的资源不同。
  2. “执行检索请求”:使用 GET 或 HEAD 请求获取最终资源。
  3. “不认为等效”:原始请求 URI 不能被新 URI 替换,因为它不等效,换句话说,它是临时的。

为什么不是302?由于第 6.4.3 节(强调我的)中的这部分解释:

由于历史原因,用户代理可以将请求方法从 POST 更改为 GET 以用于后续请求。

换句话说,用户代理可以使用相同的请求方法或不同的请求方法。规范允许 302 的灵活性不符合您的要求。


推荐阅读