Xmlhttprequest CORS请求已预检,但似乎不应预检

Xmlhttprequest CORS请求已预检,但似乎不应预检,xmlhttprequest,cors,multipartform-data,xmlhttprequest-level2,Xmlhttprequest,Cors,Multipartform Data,Xmlhttprequest Level2,以下跨源POST请求,其内容类型为多部分/表单数据,并且只预引导简单标题。根据W3C规范,除非我读错了,否则它不应该被预检。我已经在Chrome 27和Firefox 10.8.3中证实了这一点。我还没有测试过其他浏览器 以下是请求标题等: Request URL:http://192.168.130.135:8081/upload/receiver Request Method:POST Status Code:200 OK Request Headersview source Accept:

以下跨源POST请求,其内容类型为多部分/表单数据,并且只预引导简单标题。根据W3C规范,除非我读错了,否则它不应该被预检。我已经在Chrome 27和Firefox 10.8.3中证实了这一点。我还没有测试过其他浏览器

以下是请求标题等:

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
以下是选项(飞行前)请求:

规范似乎非常明确:

  • 仅限:支票
  • 仅限:支票
更新:以下是一些简单的客户端代码,它们将重现以下内容:

var xhr=new XMLHttpRequest(),
formData=新的formData();
append('myfile',someFileObj);
xhr.upload.progress=函数(e){
//在此处插入上载进度逻辑
};
xhr.open('POST','http://192.168.130.135:8080/upload/receiver",对),;
xhr.send(formData);

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

我猜
内容类型
标题上的“边界”导致了问题。如果你能复制这个,它应该作为一个浏览器错误提交,因为规范规定
内容类型
标题检查应该排除参数。

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

在XMLHttpRequest.cpp中:

void XMLHttpRequest::createRequest(例外代码&ec)
{
...
options.preflightPolicy=uploadEvents?ForcePreflight:ConsiderPreflight;
...
//上传事件监听器的存在迫使我们使用预处理,因为发布到一个不允许上传的URL
//允许跨源请求应该与发布到根本没有响应的URL完全相同。
//此外,只有异步请求支持上载进度事件。
bool uploadEvents=false;
if(m_异步){
m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
if(m_请求实体和m_上载){
uploadEvents=m_upload->hasEventListeners();
m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().loadstartEvent));
}
}
...
}

更新:Firefox似乎应用了与Webkit相同的逻辑。以下是nsXMLHttpRequest.cpp中的相关代码:

nsresult
nsXMLHttpRequest::CheckChannelForCrossSiteRequest(nsIChannel*aChannel)
{
...
//检查我们是否需要执行飞行前请求。
nsCOMPtr httpChannel=do_QueryInterface(aChannel);
NS_确保为TRUE(httpChannel,NS_ERROR_DOM_BAD_URI);
NSA自动触发方法;
httpChannel->GetRequestMethod(方法);
如果(!mCORSUnsafeHeaders.IsEmpty()||
(mUpload&&mUpload->HasListeners())||
(!method.lowercaseequalliteral(“get”)&&
!method.lowercaseequalliteral(“post”)&&
!method.lowercaseequalliteral(“head”)){
mState |=XML_HTTP_REQUEST_NEED_AC_PREFLIGHT;
}
...
}
注意条件的
mUpload&&mUpload->HasListeners()
部分


似乎Webkit和Firefox(可能还有其他人)在飞行前确定代码中插入了一些未经W3C规范认可的逻辑。如果我在规范中遗漏了什么,请发表评论。

这是我最初的怀疑,但比这更险恶。我刚刚查看了Webkit的源代码,并找出了发生这种情况的原因。我将把我的答案发布在社区维基上。这是一个惊人的发现!客户端代码触发预飞行是很奇怪的;规范中没有这方面的内容。此外,评论并没有让事情变得更清楚。我建议在WebKit板上对此进行澄清。@先生,我怀疑这种逻辑并不局限于WebKit。我在使用Firefox时也遇到了同样的问题。我还没有测试IE10。我还打算看看Firefox的源代码,看看是否能证实我的怀疑。我已经提交了一个Webkit bug,尽管这种逻辑也出现在Firefox和IE10中。所以听起来这不是一个bug。在XHR规范中搜索单词“preflight”的第二个实例:这表示上载事件强制预飞,因为上载事件引入了CORS之前不可用的新信息。然而,令人困惑的是,CORS规范中没有捕捉到这一点。很高兴发现这一点。感觉像一个量子错误:CORS错误只在我有一个上载事件侦听器时发生(如果响应是重定向,则飞行前CORS错误)
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