跨源资源共享 (CORS) post 请求可以通过纯 JavaScript 工作,但为什么不使用 jQuery
我的本地 LAN 上有一台机器(机器 A),它有两个 Web 服务器。第一个是 XBMC 中的内置库(端口 8080)并显示我们的库。第二个服务器是 CherryPy python 脚本(端口 8081),我用它来按需触发文件转换。文件转换由来自 XBMC 服务器提供的页面的 AJAX POST 请求触发。
- 转到显示库的 http://machineA:8080
- 显示
- 库 用户单击“转换”链接,该链接发出以下命令 -
jQuery Ajax 请求
$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
- 浏览器发出带有以下标头的 HTTP OPTIONS 请求;
请求标头 - 选项
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://machineA:8080
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-requested-with
- 服务器响应以下内容;
响应标头 - 选项(状态 = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:40:29 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
- 然后对话停止。理论上,浏览器应该在服务器响应正确的(?)CORS 标头(Access-Control-Allow-Origin:*)时发出 POST 请求。
为了进行故障排除,我还从 http://jquery.com。这就是我被难住的地方,来自 jquery.com,post 请求有效,一个 OPTIONS 请求在 POST 之后发送。此交易的标头如下;
请求标头 - 选项
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://jquery.com
Access-Control-Request-Method: POST
响应标头 - 选项(状态 = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
请求标头 - POST
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://jquery.com/
Content-Length: 12
Origin: http://jquery.com
Pragma: no-cache
Cache-Control: no-cache
响应标头 - POST(状态 = 200)好的)
Content-Length: 32
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: application/json
我不明白为什么同一个请求可以在一个站点上运行,但在另一个站点上却不行。我希望有人能够指出我所缺少的东西。感谢您的帮助!
I have a machine on my local lan (machineA) that has two web servers. The first is the in-built one in XBMC (on port 8080) and displays our library. The second server is a CherryPy python script (port 8081) that I am using to trigger a file conversion on demand. The file conversion is triggered by a AJAX POST request from the page served from the XBMC server.
- Goto http://machineA:8080 which displays library
- Library is displayed
- User clicks on 'convert' link which issues the following command -
jQuery Ajax Request
$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
- The browser issues a HTTP OPTIONS request with the following headers;
Request Header - OPTIONS
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://machineA:8080
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-requested-with
- The server responds with the following;
Response Header - OPTIONS (STATUS = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:40:29 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
- The conversation then stops. The browser, should in theory, issue a POST request as the server responded with the correct (?) CORS headers (Access-Control-Allow-Origin: *)
For troubleshooting, I have also issued the same $.post command from http://jquery.com. This is where I am stumped, from jquery.com, the post request works, a OPTIONS request is sent following by a POST. The headers from this transaction are below;
Request Header - OPTIONS
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://jquery.com
Access-Control-Request-Method: POST
Response Header - OPTIONS (STATUS = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
Request Header - POST
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://jquery.com/
Content-Length: 12
Origin: http://jquery.com
Pragma: no-cache
Cache-Control: no-cache
Response Header - POST (STATUS = 200 OK)
Content-Length: 32
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: application/json
I can't work out why the same request would work from one site, but not the other. I am hoping someone might be able to point out what I am missing. Thanks for your help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我终于偶然发现了这个链接“
标头添加到所有 CORS 请求中。 jQuery 1.5.2 不这样做。另外,根据同一问题,设置服务器响应标头
不允许响应继续。您需要确保响应标头明确包含所需的标头。 IE:
I finally stumbled upon this link "A CORS POST request works from plain javascript, but why not with jQuery?" that notes that jQuery 1.5.1 adds the
header to all CORS requests. jQuery 1.5.2 does not do this. Also, according to the same question, setting a server response header of
does not allow the response to continue. You need to ensure the response header specifically includes the required headers. ie:
请求:
响应:
REQUEST:
RESPONSE:
我通过使用 Jquery ajax 设置请求标头解决了使用 google 距离矩阵 API 时自己的问题。看看下面。
请注意我在设置中添加的内容
**
**
我希望这有帮助。
I solved my own problem when using google distance matrix API by setting my request header with Jquery ajax. take a look below.
Note what i added at the settings
**
**
I hope this helps.
我花了一些时间找到解决方案。
如果您的服务器响应正确并且请求出现问题,您应该将
withCredentials: true
添加到请求中的xhrFields
中:Took me some time to find the solution.
In case your server response correctly and the request is the problem, you should add
withCredentials: true
to thexhrFields
in the request:好吧,我在这个问题上挣扎了几个星期。
最简单、最合规且非 hacky 的方法可能是使用提供者 JavaScript API,它不会进行基于浏览器的调用,并且可以处理跨源请求。
例如 Facebook JavaScript API 和 Google JS API。
如果您的 API 提供程序不是最新的,并且在其响应中不支持跨源资源源“*”标头,并且没有 JS api(是的,我说的是您雅虎),您会遇到以下三个选项之一
请注意,这将更改请求 URL,因此您的 API 服务器必须能够处理 URL 末尾的 ?callback=。
将请求发送到您的 API 服务器,该服务器由您控制,并且与客户端位于同一域中,或者启用了跨源资源共享,您可以从这里将请求代理到第 3 方 API 服务器。
在您发出 OAuth 请求并需要处理用户交互的情况下可能最有用哈哈!
window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')
Well I struggled with this issue for a couple of weeks.
The easiest, most compliant and non hacky way to do this is to probably use a provider JavaScript API which does not make browser based calls and can handle Cross Origin requests.
E.g. Facebook JavaScript API and Google JS API.
In case your API provider is not current and does not support Cross Origin Resource Origin '*' header in its response and does not have a JS api (Yes I am talking about you Yahoo ),you are struck with one of three options-
Using jsonp in your requests which adds a callback function to your URL where you can handle your response.
Caveat this will change the request URL so your API server must be equipped to handle the ?callback= at the end of the URL.
Send the request to your API server which is controller by you and is either in the same domain as the client or has Cross Origin Resource Sharing enabled from where you can proxy the request to the 3rd party API server.
Probably most useful in cases where you are making OAuth requests and need to handle user interaction Haha!
window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')
这是对我有用的总结:
定义一个新函数(包装
$.ajax
以简化):用法:
也适用于
.done
、.fail
等:服务器端(在本例中为 example.com 托管),设置这些标头(在 PHP 中添加了一些示例代码):
这是我知道真正从 JS 跨域 POST 的唯一方法。
JSONP 将 POST 转换为 GET,这可能会在服务器日志中显示敏感信息。
This is a summary of what worked for me:
Define a new function (wrapped
$.ajax
to simplify):Usage:
Also works with
.done
,.fail
,etc:Server side (in this case where example.com is hosted), set these headers (added some sample code in PHP):
This is the only way I know to truly POST cross-domain from JS.
JSONP converts the POST into GET which may display sensitive information at server logs.
将其与 Laravel 结合使用解决了我的问题。只需将此标头添加到您的 jquery 请求
Access-Control-Request-Headers: x-requested-with
中,并确保您的服务器端响应已设置此标头Access-Control-Allow-Headers :*。
Using this in combination with Laravel solved my problem. Just add this header to your jquery request
Access-Control-Request-Headers: x-requested-with
and make sure that your server side response has this header setAccess-Control-Allow-Headers: *
.我遇到了完全相同的问题,jquery ajax 只在发布请求上给了我 cors 问题,而 get 请求工作正常 - 我厌倦了上面的所有内容,但没有结果。我的服务器等中有正确的标头。改用 XMLHTTPRequest 而不是 jquery 立即解决了我的问题。不管我用哪个版本的jquery都没有解决这个问题。如果您不需要向后兼容浏览器,Fetch 也可以正常工作。
希望这可以帮助其他遇到同样问题的人。
I had the exact same issue where jquery ajax only gave me cors issues on post requests where get requests worked fine - I tired everything above with no results. I had the correct headers in my server etc. Changing over to use XMLHTTPRequest instead of jquery fixed my issue immediately. No matter which version of jquery I used it didn't fix it. Fetch also works without issues if you don't need backward browser compatibility.
Hopefully this helps anyone else with the same issues.
如果由于某些原因,在尝试添加标头或设置控制策略时仍然无济于事,您可以考虑使用 apache ProxyPass...
例如,在使用 SSL 的
中添加以下两个指令:确保加载以下 apache 模块(使用 a2enmod 加载它们):
显然,您必须更改 AJAX 请求 url 才能使用 apache 代理...
If for some reasons while trying to add headers or set control policy you're still getting nowhere you may consider using apache ProxyPass…
For example in one
<VirtualHost>
that uses SSL add the two following directives:Make sure the following apache modules are loaded (load them using a2enmod):
Obviously you'll have to change your AJAX requests url in order to use the apache proxy…
这对聚会来说有点晚了,但我已经为此苦苦挣扎了几天。这是可能的,我在这里找到的答案都不起作用。这很简单。
这是 .ajax 调用:
这是服务器端的 php:
This is a little late to the party, but I have been struggling with this for a couple of days. It is possible and none of the answers I found here have worked. It's deceptively simple.
Here's the .ajax call:
Here's the php on the server side: