URL 片段和302重定向

众所周知,URL 片段(#之后的部分)不会发送到服务器。

当涉及到服务器重定向(通过 HTTP 状态302和 Location:头)时,我确实想知道片段是如何工作的。

我的问题有两方面:

  1. 如果原始 URL 有一个片段(/original.php#foo) ,并且对 /new.php进行了重定向,那么原始 URL 的片段部分是否会丢失?或者它有时被应用到新的 URL?< br > 在这种情况下,新的 URL 会是 /new.php#foo吗?

  2. 不管原始 URL 是什么,如果服务器重定向到一个带有片段(/new.php#foo)的新 URL,该片段会得到“尊重”吗?还是说服务器根本就不需要干预片段——浏览器会因此忽略它而直接转到 /new.php吗?

58220 次浏览

更新日期2022-09-22 :

RFC 9110/STD 97 HTTP 语义 (取消了7231(和其他)) ,已于2022年6月作为 INTERNET 标准发布。新编号的 第10.2.2节位置中的措辞保持与前/后相同。

2014年6月27日更新 :

RFC 7231,超文本传输协议(HTTP/1.1) : 语义和内容 ,已作为一个提议的标准发布:

Location 头字段的语法已更改为允许所有 URI 引用,包括相对引用和片段 对于何时不使用碎片进行了一些澄清 (第7.1.2条)

第7.1.2节,位置的要点是:

如果3xx (重定向)响应中提供的 Location 值 没有片段组件,用户代理必须处理 重定向,就好像该值继承 URI 的片段组件一样 用于生成请求目标的引用(即,重定向 继承原始引用的片段(如果有的话)。

例如,一个 为 URI 引用生成的 GET 请求 Http://www.example.org/~tim" ,可能导致303(见其他) 包含头字段的响应:

Location: /People.html#tim

这表明用户代理重定向到 “ http://www.example.org/people.html#tim" ;

同样,为 URI 引用生成 GET 请求 Http://www.example.org/index.html#larry" ,可能导致301(移动 包含头字段的响应:

Location: http://www.example.net/index.html

这表明用户代理重定向到 “ http://www.example.net/index.html#larry" ; ,保存原件 片段标识符。

这应该能清楚地回答你的问题。

最新消息

这是与 当前 HTTP 规范有关的一个公开(未指明)问题。 IETF httpbis 工作组的两个问题解决了这个问题:

# 6允许在 Location头中有片段。 # 43说:

我只是用不同的浏览器测试了一下。

  • Firefox 和 Safari 使用位置标题中的片段。
  • Opera 在存在时使用源 URI 中的片段,否则使用来自重定向位置的片段
  • IE (8)忽略位置 URI 中的片段,因此当存在时将使用来自源 URI 的片段

建议:

注意: 当来自原始 URI 的片段标识符和重定向需要被组合时的行为是未定义的; 当前的用户代理确实在哪个片段优先上有所不同

[...]

IE8是的似乎使用了来自 Location的片段标识符(我看到的行为可能仅限于 localhost)。

因此,对于 Safari/IE/Firefox/Chrome (刚刚测试过) ,我们似乎有一致的行为,使用 Location 头部的片段,而不管原始 URI 是什么。

因此,我改变了我的建议,以文档 那个作为预期的行为。

这将导致最兼容的浏览器和未来的证明(因为这个问题最终将得到标准化)回答你的问题:

A: 来自原始 URL 的片段被丢弃。

B: 来自 Location头部的片段是值得尊敬的。

如果发生 HTTP/3xx 重定向,Safari 5和 IE9及以下版本将删除原始 URI 的片段。如果响应中的 Location 标头指定了一个片段,则使用它。

IE10 + 、 Chrome 11 + 、 Firefox 4 + 和 Opera 都将在经过3xx 重定向后“重新附加”原始 URI 片段。

测试页面: http://www.webdbg.com/test/redir/fragment/

请参阅 http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx关于这个问题的进一步讨论

只是想让你知道,在这里你可以找到合适的规格。W3c 定义了所有人的行为: http://www.w3.org/TR/cuap#uri-条款4.1-见下文:

当资源(URI1)移动时,HTTP 重定向可以指示其 新位置(URI2)。

如果 URI1具有片段标识符 # frag,则 用户代理应该尝试达到的将是 URI2 # frag 已经有一个片段标识符,那么 # frag 不能被追加,并且 新的目标是 URI2。

错误: 大多数当前的用户代理确实实现了 HTTP 重定向,但是没有 将片段标识符附加到新的 URI,通常 使用户感到困惑,因为他们最终得到了错误的资源。

参考文献:

HTTP 重定向在 HTTP/1.1的第10.3节中进行了描述 规范[ RFC2616]。详细描述了所需的行为 在“处理重定向 URL 中的片段标识符”[ RURL ] 术语「持久性统一资源定位符(pURL)」指定一个网址(a URI 的特殊情况) ,它通过 HTTP 指向另一个 URI 有关更多信息,请参见“持久统一资源” 定位器”[ PURL ]示例:

假设用户在 Http://www.w3.org/tr/wd-ruby/#changes ,服务器重定向 用户代理到 http://www.w3.org/TR/ruby/ URI,浏览器应该将片段标识符 # 的更改追加到它: Http://www.w3.org/tr/ruby/#changes.

张贴类似的 对解决方案有异议面对我。

希望它能帮助与 preserving hash in IE对302重定向的类似要求的人。

添加重要部分的答案,而不是单独的链接

我们在应用程序中使用 SiteMinder身份验证。

我发现在验证成功之后,SiteMinder使用 登录表单隐藏变量 value(它存储用户请求的 URL /myapp/-without hash fragment,因为它不会被发送到服务器)对用户请求的应用程序页面执行 302 redirection,名称与 redirect相似。下面是样本表格

Sample login form

由于 redirect隐藏变量 价值只包含没有散列片段的 /myapp/,而且它是一个302重定向,所以散列片段甚至在到达我们的应用程序之前就被 IE 自动删除了,而且不管我们在应用程序代码中尝试的解决方案是什么,都无法实现。

IE 正在重定向到 /myapp/只,它是登陆在我们的应用程序 https://ourapp.com/myapp/#/home的默认主页。

花了将近一天的时间才搞清楚这种行为。

解决办法是:

更改了 登入表格隐藏变量(redirect) 价值以保存散列片段 附加 window.location.hash以及现有值。类似于下面的代码

$(function () {
var $redirect = $('input[name="redirect"]');
$redirect.val($redirect.val() + window.location.hash);
});

修改之后,redirect隐藏变量将用户请求的 URL 值存储为 /myapp/#/pending/requests,而 SiteMinder将其重定向到 IE 中的 /myapp/#/pending/requests

上述解决方案在所有三种浏览器 Chrome, Firefox and IE中都运行良好。

感谢@AlexFord 为本期 详细解释和提供解决方案所做的贡献。