149

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

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

我的问题实际上是双重的:

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

  2. 不管原始 URL 是什么,如果服务器重定向到带有片段 ( /new.php#foo) 的新 URL,片段会得到“尊重”吗?或者服务器真的没有业务干扰片段 - 因此浏览器会通过简单地忽略它/new.php吗?

4

4 回答 4

146

2014 年 6 月 27 日更新

RFC 7231,超文本传输​​协议 (HTTP/1.1):语义和内容,已作为提议标准发布。从变更日志

Location 标头字段的语法已更改为允许所有 URI 引用,包括相对引用和片段,以及关于何时不适合使用片段的一些说明。(第 7.1.2 节)

第 7.1.2 节的要点。地点

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

例如,为 URI 引用“http://www.example.org/~tim”生成的 GET 请求可能会导致包含标头字段的 303(请参阅其他)响应:

Location: /People.html#tim

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

同样,为 URI 引用“http://www.example.org/index.html#larry”生成的 GET 请求可能会导致包含标头字段的 301(永久移动)响应:

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

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

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

更新结束

这是当前 HTTP 规范的一个开放(未指定)问题。它在IETF httpbis 工作组的 2 个问题中得到解决:

#6 允许在标头中使用片段Location。#43 是这样说的:

我刚刚用各种浏览器测试了这个。

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

提议:

“注意:当来自原始 URI 的片段标识符和重定向需要组合时的行为是未定义的;当前的用户代理确实在哪个片段优先方面存在差异。”

[...]

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

因此,对于 Safari/IE/Firefox/Chrome(刚刚测试),我们似乎具有一致的行为,因为无论原始 URI 是什么,都使用 Location 标头中的片段。

因此,我更改了我的建议,以将其记录预期的行为。

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

答:原始 URL 的片段会被丢弃。

B:来自标头的片段Location被尊重。

于 2010-02-21T12:57:31.013 回答
46

如果发生 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对此问题的进一步讨论

于 2011-05-06T18:11:28.590 回答
12

只是让您知道,在这里您可以找到合适的规格。通过 w3c 定义所有人的行为方式:http ://www.w3.org/TR/cuap#uri - 第 4.1 条 - 见下文:

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

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

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

参考:

HTTP 重定向在 HTTP/1.1 规范 [RFC2616] 的第 10.3 节中描述。所需行为在“重定向 URL 中片段标识符的处理”[RURL] 中有详细描述。术语“持久统一资源定位器 (PURL)”指的是通过 HTTP 重定向指向另一个 URL(URI 的一种特殊情况)。有关详细信息,请参阅“持久统一资源定位符”[PURL]。例子:

假设用户在 http://www.w3.org/TR/WD-ruby/#changes请求资源,服务器将用户代理重定向到http://www.w3.org/TR/ruby/。在获取后一个 URI 之前,浏览器应该将片段标识符 #changes 添加到它: http://www.w3.org/TR/ruby/#changes

于 2012-07-01T17:23:11.597 回答
0

发布与我面临的解决方案类似的问题。

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

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

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

我发现在成功验证后,SiteMinder正在302 redirection使用名称类似于value/myapp/. 下面的示例表格without hash fragmentredirect

登录表单示例

由于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其重定向到/myapp/#/pending/requestsIE。

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

感谢@AlexFord 对此问题的详细解释并提供了解决方案

于 2020-07-15T14:49:27.617 回答