13

Poniższe żądanie POST o charakterze krzyżowym z treścią typu multipart/danych formularzy i tylko proste nagłówki jest wstępnie oświetlone. Zgodnie ze specyfikacją W3C, chyba że źle ją odczytam, nie powinien on być podświetlony. Potwierdziłem, że dzieje się to w Chrome 27 i Firefox 10.8.3. Nie testowałem żadnych innych przeglądarek.Żądanie CORS jest wstępnie podświetlone, ale wygląda na to, że nie powinno to być

Oto nagłówki żądania, 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 

A oto opcje (preflight) prośba:

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 

Spec wydaje się dość oczywiste:

UPDATE: Oto niektóre proste kodu po stronie klienta, które będą powielać to:

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); 

Czy ktoś wie dlaczego tak jest preflighted?

Odpowiedz

18

Skończyło się na sprawdzeniu kodu źródłowego Webkita, próbując to zrozumieć (po tym, jak Google nie przyniósł żadnych trafnych wyników). Okazuje się, że Webkit wymusi preflightację dowolnego żądania pochodzącego z różnych źródeł, jeśli zarejestrujesz obsługę zdarzeń onprogress. Nie jestem całkowicie pewien, nawet po przeczytaniu komentarza do kodu, dlaczego ta logika została zastosowana.

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)); 
     } 
    } 

    ... 
} 


UPDATE:: Firefox stosuje tę samą logikę jako Webkit, wydaje

W XMLHttpRequest.cpp. Oto odpowiedni kod z nsXMLHttpRequest.cpp:

nsresult 
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel* aChannel) 
{ 
    ... 

    // Check if we need to do a preflight request. 
    nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel); 
    NS_ENSURE_TRUE(httpChannel, NS_ERROR_DOM_BAD_URI); 

    nsAutoCString method; 
    httpChannel->GetRequestMethod(method); 
    if (!mCORSUnsafeHeaders.IsEmpty() || 
     (mUpload && mUpload->HasListeners()) || 
     (!method.LowerCaseEqualsLiteral("get") && 
     !method.LowerCaseEqualsLiteral("post") && 
     !method.LowerCaseEqualsLiteral("head"))) { 
     mState |= XML_HTTP_REQUEST_NEED_AC_PREFLIGHT; 
    } 

    ... 
} 

Wskazówka część mUpload && mUpload->HasListeners() warunkowego.

Wygląda na to, że Webkit i Firefox (i prawdopodobnie inne) wprowadziły pewną logikę do swojego kodu określającego preflight, który nie jest usankcjonowany przez specyfikację W3C. Jeśli brakuje mi czegoś w specyfikacji, skomentuj.

+0

To niesamowite znalezisko! To dziwne, że kod po stronie klienta uruchamia preflight; nie ma w tym nic szczególnego. Również komentarz nie czyni rzeczy bardziej przejrzystymi. Zaleciłbym wprowadzenie tego na tablicach WebKit w celu wyjaśnienia. – monsur

+0

@monsur Podejrzewam, że ta logika nie ogranicza się do Webkita. Podczas korzystania z przeglądarki Firefox napotkałem na ten sam problem. Nie testowałem jeszcze IE10. Zamierzam również rzucić okiem na źródło Firefoksa i sprawdzić, czy mogę potwierdzić moje podejrzenia. –

+0

Czy możesz zaktualizować oryginalne pytanie tak, aby zawierało kod JavaScript po stronie klienta, którego używasz do wysłania tego żądania? Pomoże to uporządkować sprawy. – monsur

1

Domyślam się, że "granica" nagłówka Content-Type powoduje problemy. Jeśli jesteś w stanie to odtworzyć, należy go zgłosić jako błąd przeglądarki, ponieważ specyfikacja stwierdza, że ​​sprawdzenie nagłówka Content-Type powinno wykluczyć parametry.

+0

To było moje początkowe podejrzenie, ale to jest bardziej złowrogie. Właśnie sprawdziłem źródło Webkita i zorientowałem się, dlaczego tak się dzieje. Opublikuję odpowiedź jako wiki społeczności. –