13

Yêu cầu POST gốc sau đây, với loại nội dung của dữ liệu nhiều phần/biểu mẫu và chỉ các tiêu đề đơn giản được xem trước. Theo thông số kỹ thuật của W3C, trừ khi tôi đọc sai, nó không nên được xem trước. Tôi đã xác nhận điều này xảy ra trong Chrome 27 và Firefox 10.8.3. Tôi chưa thử nghiệm bất kỳ trình duyệt nào khác.Yêu cầu CORS được xem trước, nhưng có vẻ như không phải là

Sau đây là các tiêu đề yêu cầu, vv:

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 

Và đây là OPTIONS (preflight) yêu cầu:

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 

Các spec dường như khá rõ ràng:

UPDATE: Dưới đây là một số mã client-side đơn giản mà sẽ tái sản xuất này:

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

Có ai biết tại sao điều này đang được preflighted?

Trả lời

18

Tôi đã kết thúc kiểm tra mã nguồn Webkit để tìm ra điều này (sau khi Google không mang lại bất kỳ lần truy cập hữu ích nào). Nó chỉ ra rằng Webkit sẽ buộc bất kỳ yêu cầu cross-origin để được preflighted chỉ đơn giản là nếu bạn đăng ký một xử lý sự kiện onprogress. Tôi không hoàn toàn chắc chắn, ngay cả sau khi đọc các bình luận mã, tại sao logic này được áp dụng.

Trong 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 áp dụng cùng một logic như Webkit, nó xuất hiện. Đây là mã có liên quan từ 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; 
    } 

    ... 
} 

Chú ý phần mUpload && mUpload->HasListeners() của điều kiện.

Có vẻ như Webkit và Firefox (và có thể là những người khác) đã chèn một số logic vào mã xác định preflight của chúng mà không bị xử lý bởi thông số W3C. Nếu tôi thiếu một cái gì đó trong spec, xin vui lòng bình luận.

+0

Đó là một tìm kiếm tuyệt vời! Mã lạ cho mã phía máy khách của nó để kích hoạt một preflight; không có gì trong spec về điều đó. Ngoài ra nhận xét không làm cho mọi thứ rõ ràng hơn. Tôi sẽ khuyên bạn nên đưa nó lên trên bảng WebKit để làm rõ. – monsur

+0

@monsur Tôi nghi ngờ logic này không bị giới hạn đối với Webkit. Tôi cũng gặp phải vấn đề tương tự khi sử dụng Firefox. Tôi chưa thử nghiệm IE10. Tôi cũng dự định xem qua nguồn Firefox và xem liệu tôi có thể xác nhận sự nghi ngờ của mình hay không. –

+0

Bạn có thể cập nhật câu hỏi ban đầu để bao gồm mã JavaScript phía máy khách mà bạn đang sử dụng để thực hiện yêu cầu này không? Điều đó sẽ giúp đưa mọi thứ vào bối cảnh. – monsur

1

Tôi đoán là "ranh giới" trên tiêu đề Content-Type đang gây ra sự cố. Nếu bạn có thể tái tạo điều này, nó sẽ được đệ trình dưới dạng lỗi trình duyệt, vì thông số nêu rõ rằng kiểm tra tiêu đề Content-Type sẽ loại trừ các tham số.

+0

Đó là nghi ngờ ban đầu của tôi, nhưng điều đó càng trở nên độc ác hơn thế. Tôi vừa kiểm tra nguồn Webkit và tìm ra lý do tại sao điều này xảy ra. Tôi sẽ đăng câu trả lời của tôi như một wiki cộng đồng. –

Các vấn đề liên quan