URL Fragment and 302 redirects
Asked Answered
O

4

157

It's well known that the URL fragment (the part after the #) is not sent to the server.

I do wonder though how fragments work when a server redirect (via HTTP status 302 and Location: header) is involved.

My question is really two-fold:

  1. If the original URL had a fragment (/original.php#foo), and a redirect is made to /new.php, does the fragment part of the original URL simply get lost? Or does it sometimes get applied to the new URL?
    Will the new URL ever be /new.php#foo in this case?

  2. Regardless of the original URL, if the server redirects to a new URL with a fragment (/new.php#foo), will the fragment get "honored"? Or does the server really have no business interfering with the fragment at all -- and will the browser therefore ignore it by simply going to /new.php??

Overstuffed answered 18/2, 2010 at 4:55 Comment(2)
Here you can find spec by W3C: w3.org/TR/cuap#uri clause 4.1. the fragment should be preserved on redirect.Dysentery
@Marcin: W3C TAG suggest differently: lists.w3.org/Archives/Public/ietf-http-wg/2010OctDec/0504.html. Related question: Is a 302 Redirect to relative URL valid, or invalid?Gandhiism
L
153

Update 2022-09-22:

RFC 9110/STD 97 HTTP Semantics (which obsoletes 7231 (and others)), has been published as an INTERNET STANDARD in June 2022. The wording in the newly numbered Section 10.2.2 Location stays the same as before/below.

Update 2014-Jun-27:

RFC 7231, Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content, has been published as a PROPOSED STANDARD. From the Changelog:

The syntax of the Location header field has been changed to allow all URI references, including relative references and fragments, along with some clarifications as to when use of fragments would not be appropriate. (Section 7.1.2)

The important points from Section 7.1.2. Location:

If the Location value provided in a 3xx (Redirection) response does not have a fragment component, a user agent MUST process the redirection as if the value inherits the fragment component of the URI reference used to generate the request target (i.e., the redirection inherits the original reference's fragment, if any).

For example, a GET request generated for the URI reference "http://www.example.org/~tim" might result in a 303 (See Other) response containing the header field:

Location: /People.html#tim

which suggests that the user agent redirect to "http://www.example.org/People.html#tim"

Likewise, a GET request generated for the URI reference "http://www.example.org/index.html#larry" might result in a 301 (Moved Permanently) response containing the header field:

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

which suggests that the user agent redirect to "http://www.example.net/index.html#larry", preserving the original fragment identifier.

This should clearly answer your questions.

Update END

this is an open (not specified) issue with the current HTTP specification. it is addressed in 2 issues of the IETF httpbis working group:

#6 allows fragments in the Location header. #43 says this:

I just tested this with various browsers.

  • Firefox and Safari use the fragment in the location header.
  • Opera uses the fragment from the source URI, when present, otherwise the fragment from the redirect location
  • IE (8) ignores the fragment in the location URI, thus will use the fragment from the source URI, when present

Proposal:

"Note: the behavior when fragment identifiers from the original URI and the redirect need to be combined is undefined; current User Agents indeed differ on what fragment takes precedence."

[...]

It appears that IE8 does use the fragment idenfitier from Location (the behavior I saw might be limited to localhost).

Thus we seem to have consistent behavior for Safari/IE/Firefox/Chrome (just tested), in that the fragment from the Location header gets used, no matter what the original URI was.

I therefore change my proposal to document that as expected behavior.

this leads to the most browser compatible and future proof (because this issue will eventually get standardized) answer to your question:

A: fragments from original URLs get discarded.

B: fragments from the Location header are honored.

Latarsha answered 21/2, 2010 at 12:57 Comment(5)
I had forgotten about some "rewrite" rules I set in HTTP servers, which were probably implemented as 301 redirect. As a consequence IE kept losing fragment identifier because when you have multiple redirects, the fragments set by the first redirect becomes part of the source URI in the second.Abate
opera 12.12 honors the fragment in the location header when present.Tapping
On the current versions of both Chrome and Firefox: A is not true. On the current version of Firefox: B is not true. At the moment, if you have to use hashes (e.g., using Backbone's routing) it seems that javascript-based redirection is your only real option.Cholent
The quoted block seems to contradict itself. First it says "IE (8) ignores the fragment in the location URI, thus will use the fragment from the source URI, when present", then later it says "It appears that IE8 does use the fragment identifier from Location". Is the first referring to something different from the second?Azelea
B is not true for Chome 45.0.2454.85. B is true for Firefox 40.0.3.Dillydally
D
48

Safari 5 and IE9 and below drop the original URI's fragment if a HTTP/3xx redirect occurs. If the Location header on the response specifies a fragment, it is used.

IE10+, Chrome 11+, Firefox 4+, and Opera will all "reattach" the original URI's fragment after following a 3xx redirection.

Test page: http://www.webdbg.com/test/redir/fragment/.

See further discussion of this issue at http://blogs.msdn.com/b/ieinternals/archive/2011/05/17/url-fragments-and-redirects-anchor-hash-missing.aspx

Drawbar answered 6/5, 2011 at 18:11 Comment(3)
Actually IE10 still behaves differently from latest Firefox and Chrome versions. It does seem to preserve the fragment from the source URL in case of a simple redirect. And if the redirect Location contains a fragment, it will keep it correctly. But if a redirected Location with a fragment goes through another 3xx redirect, it will inexplicably ignore the fragment from the first redirection, which is not consistent with the 2 previous behaviors. Chrome and Firefox consistently preserve it.Tilt
I've confirmed that you're correct. See the final test link on this page: webdbg.com/test/redir/fragmentDrawbar
It makes sense to drop the #fragment from any previous URL in a chain of redirects. You are likely going to a page where that anchor no longer applies/exists.Subset
D
12

Just to let you know, here you can find proper spec. by w3c defining how all should behave: http://www.w3.org/TR/cuap#uri - clause 4.1 - see below:

When a resource (URI1) has moved, an HTTP redirect can indicate its new location (URI2).

If URI1 has a fragment identifier #frag, then the new target that the user agent should be trying to reach would be URI2#frag. If URI2 already has a fragment identifier, then #frag must not be appended and the new target is URI2.

Wrong: Most current user agents do implement HTTP redirects but do not append the fragment identifier to the new URI, which generally confuses the user because they end up with the wrong resource.

References:

HTTP redirects are described in section 10.3 of the HTTP/1.1 specification [RFC2616]. The required behavior is described in detail in "Handling of fragment identifiers in redirected URLs" [RURL]. The term "Persistent Uniform Resource Locator (PURL)" designates a URL (a special case of a URI) that points to another one through an HTTP redirect. For more information, refer to "Persistent Uniform Resource Locators" [PURL]. Example:

Suppose that a user requests the resource at http://www.w3.org/TR/WD-ruby/#changes and the server redirects the user agent to http://www.w3.org/TR/ruby/. Before fetching that latter URI, the browser should append the fragment identifier #changes to it: http://www.w3.org/TR/ruby/#changes.

Dysentery answered 1/7, 2012 at 17:23 Comment(0)
A
0

Posting similar issue with the solution faced by me.

Hope it helps to someone with the similar requirement of preserving hash in IE for 302 redirects.

Adding essential parts of the answer instead of links alone

We use SiteMinder authentication in our application.

I figured out that after successful authentication, SiteMinder is doing 302 redirection to user requested application page by using login form hidden variable value (where it stores user requested URL /myapp/ - without hash fragment since it won't be sent to the server) with name similar to redirect. Sample form below

Sample login form

Since redirect hidden variable value contains only /myapp/ without hash fragment and it's a 302 redirect, the hash fragment is automatically removed by IE even before coming to our application and whatever the solutions we are trying in our application code are not working out.

IE is redirecting to /myapp/ only and it is landing on default home page of our app https://ourapp.com/myapp/#/home.

Have wasted almost a day to figure out this behavior.

The solution is:

Have changed the login form hidden variable (redirect) value to hold the hash fragment by appending window.location.hash along with existing value. Similar to below code

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

After this change, the redirect hidden variable is storing user requested URL value as /myapp/#/pending/requests and SiteMinder is redirecting it to /myapp/#/pending/requests in IE.

The above solution is working fine in all the three browsers Chrome, Firefox and IE.

Thanks to @AlexFord for the detailed explanation and providing solution to this issue.

Aubert answered 15/7, 2020 at 14:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.