13

La seguente richiesta POST incrociata, con un tipo di contenuto di multipart/form-data e solo le intestazioni semplici è preflight. Secondo le specifiche del W3C, a meno che non lo legga male, non dovrebbe essere preflight. Ho confermato che ciò accade in Chrome 27 e Firefox 10.8.3. Non ho testato nessun altro browser.La richiesta CORS è preflight, ma sembra che non dovrebbe essere

Qui ci sono le intestazioni di richiesta, ecc:

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 

E qui è la possibilità (preflight) Richiesta:

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 

Le specifiche sembra abbastanza chiaro:

UPDATE: Ecco alcune semplici codice lato client che riprodurre questo:

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

Qualcuno sa il motivo per cui questa viene preflight?

risposta

18

Ho finito per controllare il codice sorgente di Webkit nel tentativo di capirlo (dopo che Google non ha dato alcun risultato utile). Si scopre che Webkit costringerà qualsiasi richiesta di origine incrociata a essere sottoposta a preflight semplicemente se si registra un gestore di eventi onprogress. Non sono del tutto sicuro, anche dopo aver letto i commenti del codice, perché questa logica è stata applicata.

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

    ... 
} 


UPDATE: Firefox si applica la stessa logica Webkit, appare. Ecco il codice rilevante dal 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; 
    } 

    ... 
} 

Avviso la mUpload && mUpload->HasListeners() parte del condizionale.

Sembra che Webkit e Firefox (e forse altri) abbiano inserito alcune regole nel loro codice di preflight che non è sanzionato dalle specifiche del W3C. Se mi manca qualcosa nella specifica, si prega di commentare.

+0

Questa è una scoperta incredibile! È strano per il codice lato client attivare un preflight; non c'è nulla nelle specifiche a riguardo. Anche il commento non rende le cose più chiare. Consiglierei di farlo presente sulle schede WebKit per chiarimenti. – monsur

+0

@monsur Sospetto che questa logica non sia limitata a Webkit. Ho anche riscontrato lo stesso problema con Firefox. Non ho ancora testato IE10. Intendo dare una sbirciata anche alla fonte di Firefox e vedere se posso confermare il mio sospetto. –

+0

È possibile aggiornare la domanda originale per includere il codice JavaScript sul lato client che si sta utilizzando per effettuare questa richiesta? Ciò contribuirà a mettere le cose nel contesto. – monsur

1

La mia ipotesi è che il "limite" sull'intestazione Content-Type causi problemi. Se sei in grado di riprodurlo, dovrebbe essere archiviato come un bug del browser, poiché la specifica afferma che il controllo dell'intestazione Content-Type dovrebbe escludere i parametri.

+0

Questo era il mio primo sospetto, ma è più sinistro di così. Ho appena controllato la fonte del Webkit e ho capito perché questo sta accadendo. Pubblicherò la mia risposta come wiki della comunità. –