是否还有 HTTP 301 而不是 HTTP 308 的用例来指示资源已移动(尤其是在 ReST 服务器中)?

Posted

技术标签:

【中文标题】是否还有 HTTP 301 而不是 HTTP 308 的用例来指示资源已移动(尤其是在 ReST 服务器中)?【英文标题】:Is there still a use case for HTTP 301 rather than HTTP 308 to indicate that a resource has moved (particularly in a ReST server)? 【发布时间】:2019-04-25 10:35:54 【问题描述】:

我正在指定一个 ReST 服务。我最近偶然发现了这个IETF draft document,它可能被解释为建议 ReST 服务应该始终返回 308。请注意,该文档似乎已经过期而没有被取代(我对 IETF 流程不是很清楚)。

我之前曾想过,服务应该为 GET 返回“301 Moved Permanently”,为 POST 返回“308 Permanent Redirect”,以确保它不会被不恰当地转换为 GET(通过一些试图变得聪明的东西)。

301 和 308 的用法似乎都用 SHOULD 和 SHOULD NOTs 而不是 MUST 和 MUST NOTs 来表达,因此在哲学上还不清楚什么是“正确的事情”。

GET 的 301 和 POST 的 308 应该有效。 GET 的 308 并没有错,因为在撰写本文时,current revision 包括响应 GET 生成 308 的示例。 现在有一个部署问题,如果客户不理解 308,它应该将其视为 300(而不是 301,这对我来说更有意义)但是 308 现在已被广泛理解,所以问题变成了你是否应该或为什么应该使用 HTTP 301?

如果 308 本质上是对 301 的错误修复,为什么 301 没有在 HTTP/1.1 中正式弃用?将 POST 转换为 GET 以在 ReST 中或更一般地在 HTTP 中进行重定向是否存在合法用例?

对于 301 HTTP/1.1 说:

注意:由于历史原因,用户代理可能会更改请求 后续请求的从 POST 到 GET 的方法。

为什么这是个好主意?它在任何地方仍然有效吗?

另见:

What's the difference between HTTP 301 and 308 status codes? 它很好地涵盖了 301 和 308 之间的差异,但没有涵盖这一点。 How should client of Restful API handle http status 301 redirect upon POST? What's the deal with HTTP status code 308?

【问题讨论】:

tools.ietf.org/html/rfc7538 通常这是您的(设计)决定。就像在你的例子中那样,不会有很大的不同。但是如果你把它标准化,你就不需要担心不同的情况了。问问自己,使用较新的 308 与旧的 301 相比有什么缺点吗?如果不使用较新的。 我希望通过像 HTTP 这样定义良好的协议,我们可以朝着有一种正确的做事方式的设计前进。在这种情况下 认为它是 308(我在问“互联网”为什么我错了 - 或者可能是对的)但是如果 308 是 301 的错误修复,为什么 IETF 不弃用 301。 301 是否还有与 308 不同的合理用例? 308 不是错误修复。它是确保使用相同方法的扩展(例如 POST -> POST)。程序或浏览器如何对其做出反应取决于实现。 301不会那么快弃用。 308 是为了在协议中添加另一层保护/安全。 客户端应该如何解释状态码大部分都包含在标准中,因此它不依赖于实现。如果我为不存在的资源返回 400 而不是 404,那我就错了。有些系统,包括没有正确遵循标准的“ReSTish”API。可能存在一些歧义(301/308 可能是其中之一)。 301 不会在一夜之间从实施中消失。问题是 308 是否让它变得多余? (如果是这样,正确的做法是始终使用 308 并将 301 标记为已弃用)。 为什么这是个好主意?它在任何地方仍然有效吗? 如果我们足够幸运,我们可能会从Julian Reschke 那里获得一些意见,他创作了RFC 7538 并与菲尔丁共同创作了RFC 7231。 【参考方案1】:

如果308 本质上是对301 的错误修复,为什么301 没有在HTTP/1.1 中正式弃用?

不,不是。

定义308 状态代码的RFC 7538 不会使301 失效或过时。它只是定义了 another 状态码来填补RFC 7231 上的空白,它没有定义永久 状态码变体307:

+-------------------------------------------+-----------+-----------+
|                                           | Permanent | Temporary |
+-------------------------------------------+-----------+-----------+
| Allows changing the request method from   | 301       | 302       |
| POST to GET                               |           |           |
| Does not allow changing the request       | -         | 307       |
| method from POST to GET                   |           |           |
+-------------------------------------------+-----------+-----------+

实际上,我仍然看到301 主要用于搜索引擎优化。而且我看到一些 HTTP 客户端无法识别 308


除了 RFC,让我们看看来自 Mozilla 的 MDN Web Docs say 关于 301

超文本传输​​协议 (HTTP) 301 Moved Permanently 重定向状态响应代码表示请求的资源已明确移动到 Location 标头给出的 URL。浏览器重定向到这个页面,搜索引擎更新他们到资源的链接(在'SEO-speak'中,据说'link-juice'被发送到新的URL)。

即使规范要求在执行重定向时不要更改方法(和主体),但并非所有用户代理都与它保持一致 - 您仍然可以在那里找到这种类型的错误软件。因此,建议仅将301 代码用作GETHEAD 方法的响应,而将308 Permanent Redirect 用于POST 方法,因为在此状态下明确禁止更改方法。

现在看看 Mozilla says 对 308 的看法:

超文本传输​​协议 (HTTP) 308 Permanent Redirect 重定向状态响应代码表明请求的资源已明确移动到由 Location 标头给出的 URL。浏览器重定向到这个页面,搜索引擎更新他们到资源的链接(在'SEO-speak'中,据说'link-juice'被发送到新的URL)。

请求方法和正文不会更改,而 301 有时可能会错误地更改为 GET 方法。

注意:某些 Web 应用程序可能会以非标准方式和其他目的使用 308 Permanent Redirect。例如,Google Drive 使用308 Resume Incomplete 响应向客户端指示不完整的上传何时停止。 (reference)

【讨论】:

如果不解释为什么“允许将请求方法从 POST 更改为 GET”是个好主意,我无法接受这个答案,因为这是区别的症结所在。

以上是关于是否还有 HTTP 301 而不是 HTTP 308 的用例来指示资源已移动(尤其是在 ReST 服务器中)?的主要内容,如果未能解决你的问题,请参考以下文章

C# HttpWebRequest - 如何确定是不是发生了 HTTP 301?

http 301 302 303 307 308 傻傻分不清

如何使用 301 重定向而不是 302 将 HTTP 站点重定向到 HTTPS 站点

在codeigniter中打开SSL认证网站时,301不会在http上重定向而不是重定向302

301 和 301 http 重定向是不是可以使用 expires 标头进行缓存?

Azure web.config 永久重定向并获得 307 状态码而不是 301