CORS 请求已预检,但似乎不应该 [英] CORS request is preflighted, but it seems like it should not be

查看:21
本文介绍了CORS 请求已预检,但似乎不应该的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下跨域 POST 请求的内容类型为 multipart/form-data 并且仅预检了简单的标头.根据 W3C 规范,除非我读错了,否则不应预检.我已经确认这发生在 Chrome 27 和 Firefox 10.8.3 中.我没有测试任何其他浏览器.

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 in Chrome 27 and Firefox 10.8.3. I haven't tested any other browsers.

这里是请求标头等:

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

这是 OPTIONS(预检)请求:

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

规范似乎很清楚:

  • Only simple headers: CHECK
  • Only simple methods: CHECK

更新:这里有一些简单的客户端代码可以重现这个:

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

有人知道为什么要预检吗?

Does anyone know why this is being preflighted?

推荐答案

我最终检查了 Webkit 源代码以试图解决这个问题(在 Google 没有产生任何有用的点击之后).事实证明,只要您注册一个 onprogress 事件处理程序,Webkit 就会强制预检任何跨域请求.即使在阅读了代码注释之后,我也不完全确定为什么要应用这种逻辑.

I ended up checking out the Webkit source code in an attempt to figure this out (after Google did not yield any helpful hits). It turns out that Webkit will force any cross-origin request to be preflighted simply if you register an onprogress event handler. I'm not entirely sure, even after reading the code comments, why this logic was applied.

在 XMLHttpRequest.cpp 中:

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

    ...
}


更新: Firefox 应用与 Webkit 相同的逻辑,看起来.以下是来自 nsXMLHttpRequest.cpp 的相关代码:


UPDATE: Firefox applies the same logic as Webkit, it appears. Here is the relevant code from 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;
    }

    ...
}

注意 mUpload &&mUpload->HasListeners() 部分条件.

似乎 Webkit 和 Firefox(可能还有其他)在他们的预检代码中插入了一些未被 W3C 规范认可的逻辑.如果我在规范中遗漏了什么,请发表评论.

Seems like Webkit and Firefox (and possibly others) 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 comment.

这篇关于CORS 请求已预检,但似乎不应该的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆