Subject: Re: #160: Redirects and non-GET methods

From: Julian Reschke <[email-masked]>
Date: Sat, 06 Aug 2011 12:48:35 +0200

On 2011-07-17 13:16, Mark Nottingham wrote:
> <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/160>
>
> I've just tested the latest iterations of the browsers, with the following results:
>
> • Safari/533.21.1 - all 301, 302, 307 rewritten to GET; 303 methods are preserved
> • Firefox/5.0.1 - all 301, 302 rewritten to GET; 303 and 307 methods are preserved
> • Chrome/14.0.814.0 - all 301, 302 rewritten to GET; 303 and 307 methods are preserved
> • Opera/11.50 - all 301, 302 rewritten to GET; 303 methods are preserved; 307 tests crash the browser
> • MSIE/9.0 (latest) - all 301, 302 methods preserved except POST (changed to GET); all 303, 307 methods are preserved
>
> So, many browsers rewrite many methods to GET on 301 and 302. whereas most browsers preserve methods on 303 and 307*.
>
> We *could* codify this practice. However, as Julian notes in the bug, the fact that IE doesn't rewrite anything except POST is an existence proof (and a fairly large one) that it's workable to not rewrite the method on non-POST methods.
>
> So, I'm inclined to agree that we could address this by changing 301 an 302 to note that POST is rewritten to GET; it's a smaller change, although it would require changes in more browsers.
>
> Thoughts? Especially from browser people?
> ...

In the meantime, it might make sense to look at the test cases at 
<http://www.mnot.net/javascript/xmlhttprequest/> and tune them so that 
they are a bit closer to what our plan is.

Observations:

- the tests apparently fail to handle HEAD properly, as they used the 
response body to echo the method name; maybe this can be fixed by moving 
it into a custom response header

- the tests report a failure if POST->301/302 is rewritten to GET; it 
might be useful to note that this may become compliant in HTTPbis 
(that's our intent, right?)

- I'm a bit unsure about what we should say about HEAD->303. IE's XHR 
apparently rewrites to GET, but the result probably doesn't make a 
difference for users of XHR. However, do we need to clarify the text 
about 303?

Best regards, Julian

---

From: Mark Nottingham <[email-masked]>
Date: Mon, 8 Aug 2011 15:10:36 +1000

Just for the record -- these tests need to be rewritten, ideally from scratch. That said...

On 06/08/2011, at 8:48 PM, Julian Reschke wrote:

> - the tests apparently fail to handle HEAD properly, as they used the response body to echo the method name; maybe this can be fixed by moving it into a custom response header

Fixed.

> - the tests report a failure if POST->301/302 is rewritten to GET; it might be useful to note that this may become compliant in HTTPbis (that's our intent, right?)

If that happens, yes.

> - I'm a bit unsure about what we should say about HEAD->303. IE's XHR apparently rewrites to GET, but the result probably doesn't make a difference for users of XHR. However, do we need to clarify the text about 303?

Well, the idea of HEAD is to avoid the transfer of the body, so my initial thought is that it should be preserved.

Cheers,

--
Mark Nottingham   http://www.mnot.net/

---

From: Julian Reschke <[email-masked]>
Date: Mon, 08 Aug 2011 09:20:48 +0200

> Well, the idea of HEAD is to avoid the transfer of the body, so my initial thought is that it should be preserved.

Makes sense. So we should clarify the text for 303. Do we need a new 
ticket for that?

Best regards, Julian

---

From: Mark Nottingham <[email-masked]>
Date: Mon, 8 Aug 2011 17:25:12 +1000

Yes; please go ahead and open one.

On 08/08/2011, at 5:20 PM, Julian Reschke wrote:

> Makes sense. So we should clarify the text for 303. Do we need a new ticket for that?
> 
> Best regards, Julian

---

From: Julian Reschke <[email-masked]>
Date: Mon, 08 Aug 2011 10:10:22 +0200

> Yes; please go ahead and open one.

-> <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/310>

---

From: Julian Reschke <[email-masked]>
Date: Wed, 24 Aug 2011 21:41:16 +0200

> <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/160>

I think to make things clearer, we need more introductory text, instead 
if repeating ourselves all over again in the individual status descriptions.

Here's an attempt to describe the different types of redirects:

    There are several types of redirects:

    o  Redirects due to a new URI being assigned to the resource, either
       temporarily or permanently -- the original request will need to be
       repeated against the URI specified in the Location header field.

       In this specification, the status codes 301 (Moved Permanently),
       302 (Found), and 307 (Temporary Redirect) fall under this
       category.

    o  Redirects to a new location that represents an indirect response
       to the request, such as the result of a POST operation to be
       retrieved with a subsequent GET request.  This is status code 303
       (See Other).

    o  Redirects offering a choice of matching resources for use by
       agent-driven content negotiation (Section 5.2 of [Part3]).  This
       is status code 300 (Multiple Choices).

    o  Other kinds of redirects, such as to a cached result (status code
       304 (Not Modified)).

Feedback appreciated, Julian

---

From: Mark Nottingham <[email-masked]>
Date: Tue, 30 Aug 2011 22:18:44 +1000

In situ proposal, with a few tweaks:

"""
8.3.  Redirection 3xx

This class of status code indicates that further action needs to be taken by the user agent in order to fulfil the request.

  o  Redirection of the request to another URI, either temporarily or permanently. The new URI is specified in the Location header. In this specification, the status codes 301 (Moved Permanently), 302 (Found), and 307 (Temporary Redirect) fall under this category.

  o  Redirection to a new location that represents an indirect response to the request, such as the result of a POST operation to be retrieved with a subsequent GET request.  This is status code 303 (See Other).

  o  Redirection offering a choice of matching resources for use by agent-driven content negotiation (Section 5.2 of [Part3]).  This is status code 300 (Multiple Choices).

  o  Other kinds of redirection, such as to a cached result (status code 304 (Not Modified)).

When redirection results in a new URI, user agents MUST NOT automatically make a request to it UNLESS the request method to be used is safe (Section 7.1.1). 

Clients SHOULD detect and intervene in cyclical redirections (i.e., "infinite" redirection loops).

    Note: An earlier version of this specification recommended a maximum of five redirections ([RFC2068], Section 10.3).  Content developers need to be aware that some clients might implement such a fixed limitation.
"""

On 25/08/2011, at 5:41 AM, Julian Reschke wrote:

> I think to make things clearer, we need more introductory text, instead if repeating ourselves all over again in the individual status descriptions.
>

---

From: Julian Reschke <[email-masked]>
Date: Tue, 30 Aug 2011 17:42:05 +0200

> In situ proposal, with a few tweaks:

Adopted most of this, see 
<http://trac.tools.ietf.org/wg/httpbis/trac/attachment/ticket/160/160.diff>. 
I believe this is a good starting point; with this we can simplify the 
individual status descriptions.

The one thing I did not adopt is

> When redirection results in a new URI, user agents MUST NOT automatically make a request to it UNLESS the request method to be used is safe (Section 7.1.1).

...which I believe affects 
<http://trac.tools.ietf.org/wg/httpbis/trac/ticket/238>.

Best regards, Julian

---

From: Mark Nottingham <[email-masked]>
Date: Wed, 31 Aug 2011 09:23:58 +1000

On 31/08/2011, at 1:42 AM, Julian Reschke wrote:

> Adopted most of this, see <http://trac.tools.ietf.org/wg/httpbis/trac/attachment/ticket/160/160.diff>. I believe this is a good starting point; with this we can simplify the individual status descriptions.
> 
> ...which I believe affects <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/238>.

Yes, but that issue hasn't been addressed yet; I was just preserving what's already in the draft (effectively; may have done some editorial work).

Cheers

---

From: Julian Reschke <[email-masked]>
Date: Wed, 31 Aug 2011 08:12:59 +0200

On 2011-08-31 01:23, Mark Nottingham wrote:
>> Adopted most of this, see<http://trac.tools.ietf.org/wg/httpbis/trac/attachment/ticket/160/160.diff>. I believe this is a good starting point; with this we can simplify the individual status descriptions.
>>
>> ...which I believe affects<http://trac.tools.ietf.org/wg/httpbis/trac/ticket/238>.
>
>

Actually, what the current draft has is:

"The action required MAY be carried out by the user agent without 
interaction with the user if and only if the method used in the second 
request is known to be "safe", as defined in Section 6.1.1." ...

Best regards, Julian

---

From: Mark Nottingham <[email-masked]>
Date: Wed, 31 Aug 2011 16:15:18 +1000

On 31/08/2011, at 4:12 PM, Julian Reschke wrote:

> "The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is known to be "safe", as defined in Section 6.1.1." ...

Right. The problem is that when you combine that requirement with the proposed text, it doesn't make a lot of sense, because there is no "second request' for a 304 response...

---

From: Julian Reschke <[email-masked]>
Date: Wed, 31 Aug 2011 10:17:14 +0200

> Right. The problem is that when you combine that requirement with the proposed text, it doesn't make a lot of sense, because there is no "second request' for a 304 response...

Indeed, but that's a problem with the old text as well.

Let's do a minimal fix, so that we can treat issue #238 as separate 
problem...:

"If the required action involves a subsequent HTTP request, it MAY be 
carried out by the user agent without interaction with the user if and 
only if the method used in the second request is known to be "safe", as 
defined in Section 6.1.1."

Best regards, Julian

---

From: Julian Reschke <[email-masked]>
Date: Wed, 31 Aug 2011 10:54:12 +0200

> -> <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/310>

Roy came up with a new intro for 303:

    The 303 status code indicates that the server is redirecting the
    user agent to a different resource, as indicated by a URI in the
    Location header field, that is intended to provide an indirect
    response to the original request.  In order to satisfy the original
    request, a user agent SHOULD perform a retrieval request using the
    Location URI, which may itself be redirected further, and present
    the eventual result as an answer to the original request.
    Note that the new URI in the Location header field is not considered
    equivalent to the effective request URI.

...which as a side effect avoids the explicit mention of GET; so I think 
we can close #310.

See <http://trac.tools.ietf.org/wg/httpbis/trac/changeset/1421>.

Best regards, Julian

---

From: Julian Reschke <[email-masked]>
Date: Wed, 31 Aug 2011 16:30:50 +0200

On 2011-08-31 10:17, Julian Reschke wrote:
>>> interaction with the user if and only if the method used in the
>>> second request is known to be "safe", as defined in Section 6.1.1." ...
>>
>> Right. The problem is that when you combine that requirement with the
>> proposed text, it doesn't make a lot of sense, because there is no
>> "second request' for a 304 response...
>

I did some more work, adding a note explaining the history of 
301/302/303/307 (removing the text from the individual descriptions), 
and add text allowing the rewrite of POST->GET for 301/302 (this is what 
issue 160 is about).

With this Section 7.3 would become:

7.3.  Redirection 3xx

    This class of status code indicates that further action needs to be
    taken by the user agent in order to fulfill the request.  If the
    required action involves a subsequent HTTP request, it MAY be carried
    out by the user agent without interaction with the user if and only
    if the method used in the second request is known to be "safe", as
    defined in Section 6.1.1.

    1.  Redirects of the request to another URI, either temporarily or
        permanently.  The new URI is specified in the Location header
        field.  In this specification, the status codes 301 (Moved
        Permanently), 302 (Found), and 307 (Temporary Redirect) fall
        under this category.

    2.  Redirection to a new location that represents an indirect
        response to the request, such as the result of a POST operation
        to be retrieved with a subsequent GET request.  This is status
        code 303 (See Other).

    3.  Redirection offering a choice of matching resources for use by
        agent-driven content negotiation (Section 5.2 of [Part3]).  This
        is status code 300 (Multiple Choices).

    4.  Other kinds of redirection, such as to a cached result (status
        code 304 (Not Modified)).

       Note: In HTTP/1.0, only the status codes 301 (Moved Permanently)
       and 302 (Found) were defined for the first type of redirect, and
       the second type did not exist at all ([RFC1945], Section 9.3).
       However it turned out that web forms using POST expected redirects
       to change the operation for the subsequent request to retrieval
       (GET).  To address this use case, HTTP/1.1 introduced the second
       type of redirect with the status code 303 (See Other) ([RFC2068],
       Section 10.3.4).  As user agents did not change their behavior due
       to backwards compatibility reasons, the first revision of HTTP/1.1
       added yet another status code, 307 (Temporary Redirect), for which
       the backwards compatibility problems did not apply ([RFC2616],
       Section 10.3.8).  Over 10 years later, most user agents still do
       method rewriting for status codes 301 and 302, therefore this
       specification make that behavior compliant in case the original
       request was POST.

    Clients SHOULD detect and intervene in cyclical redirections (i.e.,
    "infinite" redirection loops).

       Note: An earlier version of this specification recommended a
       maximum of five redirections ([RFC2068], Section 10.3).  Content
       developers need to be aware that some clients might implement such
       a fixed limitation.

7.3.1.  300 Multiple Choices

    The target resource has more than one representation, each with its
    own specific location, and agent-driven negotiation information
    (Section 5 of [Part3]) is being provided so that the user (or user
    agent) can select a preferred representation by redirecting its
    request to that location.

    Unless it was a HEAD request, the response SHOULD include a
    representation containing a list of representation metadata and
    location(s) from which the user or user agent can choose the one most
    appropriate.  The data format is specified by the media type given in
    the Content-Type header field.  Depending upon the format and the
    capabilities of the user agent, selection of the most appropriate
    choice MAY be performed automatically.  However, this specification
    does not define any standard for such automatic selection.

    If the server has a preferred choice of representation, it SHOULD
    include the specific URI for that representation in the Location
    field; user agents MAY use the Location field value for automatic
    redirection.

    Caches MAY use a heuristic (see Section 2.3.1.1 of [Part6]) to
    determine freshness for 300 responses.

7.3.2.  301 Moved Permanently

    The target resource has been assigned a new permanent URI and any
    future references to this resource SHOULD use one of the returned
    URIs.  Clients with link editing capabilities ought to automatically
    re-link references to the effective request URI to one or more of the
    new references returned by the server, where possible.

    Caches MAY use a heuristic (see Section 2.3.1.1 of [Part6]) to
    determine freshness for 301 responses.

    The new permanent URI SHOULD be given by the Location field in the
    response.  Unless the request method was HEAD, the representation of
    the response SHOULD contain a short hypertext note with a hyperlink
    to the new URI(s).

    If the 301 status code is received in response to a request method
    that is known to be "safe", as defined in Section 6.1.1, then the
    request MAY be automatically redirected by the user agent without
    confirmation.  Otherwise, the user agent MUST NOT automatically
    redirect the request unless it can be confirmed by the user, since
    this might change the conditions under which the request was issued.

       Note: For historic reasons, user agents MAY change the request
       method from POST to GET for the subsequent request.  If this
       behavior is undesired, status code 307 (Temporary Redirect) can be
       used instead.

7.3.3.  302 Found

    The target resource resides temporarily under a different URI.  Since
    the redirection might be altered on occasion, the client SHOULD
    continue to use the effective request URI for future requests.

    The temporary URI SHOULD be given by the Location field in the
    response.  Unless the request method was HEAD, the representation of
    the response SHOULD contain a short hypertext note with a hyperlink
    to the new URI(s).

    If the 302 status code is received in response to a request method
    that is known to be "safe", as defined in Section 6.1.1, then the
    request MAY be automatically redirected by the user agent without
    confirmation.  Otherwise, the user agent MUST NOT automatically
    redirect the request unless it can be confirmed by the user, since
    this might change the conditions under which the request was issued.

       Note: For historic reasons, user agents MAY change the request
       method from POST to GET for the subsequent request.  If this
       behavior is undesired, status code 307 (Temporary Redirect) can be
       used instead. [[issue312: but see
       <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/312>]]

   (....remainder unchanged)

See <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/160>; feedback 
appreciated.

Best regards, Julian

PS: and yes, there are more open issues regarding redirects; this change 
is for issue 160 only.

---

From: Mark Nottingham <[email-masked]>
Date: Thu, 1 Sep 2011 08:02:28 +1000

+1

On 01/09/2011, at 12:30 AM, Julian Reschke wrote:

> I did some more work, adding a note explaining the history of 301/302/303/307 (removing the text from the individual descriptions), and add text allowing the rewrite of POST->GET for 301/302 (this is what issue 160 is about).
> 
> See <http://trac.tools.ietf.org/wg/httpbis/trac/ticket/160>; feedback appreciated.
> 
> Best regards, Julian
> 
> PS: and yes, there are more open issues regarding redirects; this change is for issue 160 only.
>

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 1 Sep 2011 00:22:49 +0200

Hi Julian,

Nice work, really ! It's very clear this way and the history will
help some developers understand that what they once believed might
have evolved.

I noticed a very minor typo though :

> 7.3.  Redirection 3xx
(...)
>        code 304 (Not Modified)).
(...)
>       specification make that behavior compliant in case the original
                      ^^^^ makes

Best regards,
Willy

---

From: Karl Dubost <[email-masked]>
Date: Wed, 31 Aug 2011 18:32:31 -0400

Le 31 août 2011 à 10:30, Julian Reschke a écrit :
> I did some more work, adding a note explaining the history of 301/302/303/307 

Julian. Gorgeous.
And the history notes are a cool.
It's a lot better for understanding. 
Thanks.

-- 
Karl Dubost - http://dev.opera.com/
Developer Relations & Tools, Opera Software

---

From: Mark Nottingham <[email-masked]>
Date: Thu, 1 Sep 2011 10:21:23 +1000

Is this going to confuse new readers?

Can we clarify with something like

"""
...perform a retrieval request (i.e., a GET, unless the original method was HEAD)...
"""

?

On 31/08/2011, at 6:54 PM, Julian Reschke wrote:

> ...which as a side effect avoids the explicit mention of GET; so I think we can close #310.
>

---

From: "Roy T. Fielding" <[email-masked]>
Date: Wed, 31 Aug 2011 18:31:02 -0700

> Is this going to confuse new readers?

New readers don't know what retrieval means?

> ...perform a retrieval request (i.e., a GET, unless the original method was HEAD)...

The problem is that the redirect might be to any URI,
and thus the next request might not be HTTP.

....Roy

---

From: Mark Nottingham <[email-masked]>
Date: Thu, 1 Sep 2011 11:33:47 +1000

> New readers don't know what retrieval means?

Considering all of the issues we've had with other redirects and methods, I'm wary of making it more abstract...

> and thus the next request might not be HTTP.

Ah. How about

"... perform a retrieval request (in HTTP, a GET, unless the original method was HEAD)..."

---

From: Amos Jeffries <[email-masked]>
Date: Thu, 01 Sep 2011 16:02:34 +1200

On Thu, 1 Sep 2011 11:33:47 +1000, Mark Nottingham wrote:
> Considering all of the issues we've had with other redirects and
> methods, I'm wary of making it more abstract...
>
>

 I know part 1 section 2.1 only mentions GET when mentioning retrieval 
 methods. But my reading of part 2 section 7 definitions from *-16 
 clearly implies GET, HEAD and OPTIONS are all retrieval methods for 
 different things.

 So... I think that can just as easily be stated:

   perform a retrieval request (i.e. GET or HEAD)

 The case which may seem odd is when doing a HEAD and following with a 
 GET, but then there should have either been no changes by the system, or 
 any changes done did not require a body in the original request. ie all 
 those forms using GET method to post URL parameters could as easily use 
 HEAD and save on reply bandwidth, inline with the definition of HEAD 
 being identical to GET without a reply body.

 AYJ