New issue
Advanced search Search tips

Issue 765898 link

Starred by 3 users

Issue metadata

Status: ExternalDependency
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 2
Type: Bug



Sign in to add a comment

XHR preserves Content-Type on cross-origin 303 redirect

Reported by br...@architechies.com, Sep 16 2017

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36

Steps to reproduce the problem:
1. Set up Javascript such that a page on foo.example.com makes a multipart/form-data POST request to bar.example.com through XMLHttpRequest, which issues a 303 redirect back to a page on foo.example.com.
2. Cause this XHR to be run.

What is the expected behavior?
XMLHttpRequest sends a POST request to bar.example.com with a multipart/form-data Content-Type header, receives the 303 response, and sends a GET request to foo.example.com with no Content-Type header (since there is no payload in the request for Content-Type to describe).

What went wrong?
The GET request has a Content-Type of multipart/form-data. This may cause foo.example.com to try to read the nonexistent body.

Did this work before? N/A 

Chrome version: 59.0.3071.86  Channel: stable
OS Version: OS X 10.12.6
Flash Version: 

I've attached HAR files of the POST and GET that I ran which experienced this behavior.

It's not clear if RFC 7231 actually forbids a request like this—I can't find anything explicitly forbidding Content-Type on a payload-less request. Nevertheless, at least Rails 3.2.22.5 *does* assume that the presence of a Content-Type header indicates there is a body to read, and raises an exception when it immediately encounters an EOF.
 
post.har
499 KB Download
get.har
499 KB Download
Components: -Blink Blink>Network>XHR
Cc: annevank...@gmail.com
In https://fetch.spec.whatwg.org/#http-redirect-fetch, the spec says:

 If either actualResponse’s status is 301 or 302 and request’s method is `POST`, or actualResponse’s status is 303, set request’s method to `GET` and request’s body to null.

But it doesn't say anything about the Content-Type header. So I guess it works as specified.
You may be right, but I've become more convinced that the result is definitely wrong. RFC 7231 §3.1.1.5 says:

   The "Content-Type" header field indicates the media type of the
   associated representation: either the representation enclosed in the
   message payload or the selected representation, as determined by the
   message semantics.

In this request, there is no message payload or selected representation, so it cannot have a media type, and any Content-Type header is by definition false.

That's bad because RFC 7230 § 2.5 says:

   A sender MUST NOT generate protocol elements that convey a
   meaning that is known by that sender to be false.

It's hard to see how the HTTP-redirect fetch algorithm is not generating the request in question--it says to "set...request’s body to null", which is what makes the Content-Type header inaccurate--so the HTTP-redirect fetch algorithm is "generating protocol elements that convey a meaning that is known by that sender to be false". 

And just to be clear, RFC 2119 §2 says:

   MUST NOT   This phrase, or the phrase "SHALL NOT", mean that the
   definition is an absolute prohibition of the specification.

So doing this violates an "absolute prohibition" of the HTTP standard.
I don't think it's necessarily true that it's forbidden to set Content-Type on a missing payload, especially with HTTP folks arguing there's not a difference between empty and missing. However, it's probably worth raising an issue over at  https://github.com/whatwg/fetch/issues/new and see what mnot et al have to say. We could easily enough remove the Content-Type header for a select set of redirects. Would you be willing to do that?
yhirano: We do actually strip Content-Type on redirects here. I'm guessing this logic got lost with Blink taking over some subset of redirects?
https://cs.chromium.org/chromium/src/net/url_request/url_request.cc?rcl=cc8362b453ba41cd03f289e17e022eb6353e6946&l=934

Unlike the Origin logic there which is all kinds of a mess, the Content-Type and Content-Length stripping was intentional in http://codereview.chromium.org/10873 and  issue #843 . If nothing else, we should certainly be consistent. I agree with the reporter that leaving that header in there does not make much sense. The redirect logic strips off the request body, which means it's fair game for it to strip the two headers associated with the request body.
Cc: davidben@chromium.org
Redirects for XHR / fetch are sorely handled by Blink, so the logic is not currently used.

I'm not opposing to remove the header, but I would like the fetch spec to be explicit about it if we do such things.
Cc: kkaluri@chromium.org
Labels: Needs-Milestone TE-NeedsTriageHelp
Unable to triage this issue from TE-end, hence adding TE-NeedsTriageHelp for further triage.

Comment 9 by ricea@chromium.org, Sep 28 2017

Filed https://github.com/whatwg/fetch/issues/609 to try to get clarity on the spec issue.
Status: ExternalDependency (was: Unconfirmed)

Sign in to add a comment