Bug 117577 - CORS XHR request is always preflighted if upload progress handler is registered - W3C spec violation?
Summary: CORS XHR request is always preflighted if upload progress handler is register...
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: XML (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-06-12 19:15 PDT by Ray Nicholus
Modified: 2013-06-13 18:07 PDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ray Nicholus 2013-06-12 19:15:16 PDT
The following cross-origin POST request, with a content-type of multipart/form-data and only simple headers is preflighted. According to the W3C spec, unless I am reading it wrong, it should not be preflighted. I've confirmed this happens with Chrome.  I have not tested Safari, but the code I will point out at the end of this report shows that this is a Webkit issue.

Here are the request headers, etc:

Request URL:http://192.168.130.135:8081/upload/receiver
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:27129
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryix5VzTyVtCMwcNv6
Host:192.168.130.135:8081
Origin:http://192.168.130.135:8080
Referer:http://192.168.130.135:8080/test/raytest-jquery.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.37 Safari/537.36


And here is the OPTIONS (preflight) request:

Request URL:http://192.168.130.135:8081/upload/receiver
Request Method:OPTIONS
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:origin, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:192.168.130.135:8081
Origin:http://192.168.130.135:8080
Referer:http://192.168.130.135:8080/test/raytest-jquery.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.37 Safari/537.36
The spec seems pretty clear:

Only simple headers: CHECK
Only simple methods: CHECK


Here's some simple client-side code that will reproduce this:

var xhr = new XMLHttpRequest(),
    formData = new FormData();

formData.append('myfile', someFileObj);

xhr.upload.progress = function(e) {
    //insert upload progress logic here
};

xhr.open('POST', 'http://192.168.130.135:8080/upload/receiver', true);
xhr.send(formData);



According to the W3C spec, this request should not be preflighted, as far as I can tell.  So, I dove into the Webkit source code, and found this in XMLHttpRequest.cpp:

void XMLHttpRequest::createRequest(ExceptionCode& ec)
{
    ...

    options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;

    ...

    // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
    // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
    // Also, only async requests support upload progress events.
    bool uploadEvents = false;
    if (m_async) {
        m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
        if (m_requestEntityBody && m_upload) {
            uploadEvents = m_upload->hasEventListeners();
            m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
        }
    }

    ...
}


The same behavior is exhibited in Firefox, and I confirmed that the Firefox source uses the same logic.  IE10 also does this, but I can't verify since Microsoft doesn't make the source available.  Seems like Webkit, Firefox, and IE10 have inserted some logic into their preflight-determination code that is not sanctioned by the W3C spec. If I'm missing something in the spec, please let me know.
Comment 1 Ray Nicholus 2013-06-13 10:12:04 PDT
Turns out this is not a bug.  The spec for XMLHttpRequest does mention that upload progress event handlers should cause the "force preflight" flag to be set.  I was a bit confused when this was not specifically mentioned in the CORS spec, even though that spec does reference the existence of a "force preflight" flag.