jQuery 跨域 AJAX 请求不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22389694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cross-domain AJAX request not working
提问by Don
I'm calling POST on a third-party API that I've been working with via jQuery's $.ajax function. However, when I make the call I get the following error: XMLHttpRequest cannot load http://the-url.com. The request was redirected to 'http://the-url.com/anotherlocation', which is disallowed for cross-origin requests that require preflight.
我正在通过 jQuery 的 $.ajax 函数在我一直使用的第三方 API 上调用 POST。但是,当我拨打电话时,出现以下错误:XMLHttpRequest cannot load http://the-url.com. The request was redirected to 'http://the-url.com/anotherlocation', which is disallowed for cross-origin requests that require preflight.
I saw from this postthat this might be a Webkit bug, so I tried it in Firefox (I'm developing in Chrome) and I got the same result.I've tried this on Chrome and Firefox and I get the same result.
我从这篇文章中看到这可能是一个 Webkit 错误,所以我在 Firefox 中进行了尝试(我正在 Chrome 中开发)并且得到了相同的结果。我已经在 Chrome 和 Firefox 上尝试过,得到了相同的结果。
Per this post, I also tried using jsonp both by setting the crossDomain
property of the $.ajax function to true
and setting the dataType
to jsonp
. But, this caused a 500 internal server error.
根据这篇文章,我还尝试通过将crossDomain
$.ajax 函数的属性true
设置为并将 设置为dataType
来使用 jsonp jsonp
。但是,这导致了 500 内部服务器错误。
When I start Chrome with the --disable-web-security flag, I don't have any problems. However, if I start the browser normally, then I get the error.
当我使用 --disable-web-security 标志启动 Chrome 时,我没有任何问题。但是,如果我正常启动浏览器,则会出现错误。
So, I guess this might sort of be a 2-part question. What can I do to make this cross-domain request? If JSONP is the answer, then how do I go about figuring out if the third-party API is set up correctly to support this?
所以,我想这可能是一个由两部分组成的问题。我该怎么做才能发出这个跨域请求?如果 JSONP 是答案,那么我该如何确定第三方 API 是否正确设置以支持这一点?
EDIT:Here's the screenshot when I make the call with the browser security disabled: https://drive.google.com/file/d/0Bzo7loNBQcmjUjk5YWNWLXM2SVE/edit?usp=sharing
编辑:这是我在禁用浏览器安全性的情况下拨打电话时的屏幕截图:https: //drive.google.com/file/d/0Bzo7loNBQcmjUjk5YWNWLXM2SVE/edit?usp=sharing
Here's the screenchost when I make the call with the browser security enabled (like normal): https://drive.google.com/file/d/0Bzo7loNBQcmjam5NQ3BKWUluRE0/edit?usp=sharing
这是我在启用浏览器安全性的情况下拨打电话时的屏幕截图(像正常一样):https://drive.google.com/file/d/0Bzo7loNBQcmjam5NQ3BKWUluRE0/edit?usp=sharing
采纳答案by Don
The solution that I came up with was to use cURL (as @waki mentioned), but a slightly modified version that supports SOAP. Then, instead of making the AJAX call to the third party API (which is configured incorrectly) I make the call to my local PHP file which then makes a SOAP call to third party API and passes the data back to my PHP file where I can then process it. This allows me to forget about CORS and all of the complexities associated with it. Here's the code (taken and modified from thisquestion, but without the authentication).
我想出的解决方案是使用 cURL(正如@waki 提到的),但是一个支持 SOAP 的稍微修改过的版本。然后,我没有调用第三方 API(配置不正确)的 AJAX 调用,而是调用本地 PHP 文件,然后调用第三方 API 的 SOAP 并将数据传回我的 PHP 文件,我可以然后处理它。这让我可以忘记 CORS 以及与之相关的所有复杂性。这是代码(从这个问题中获取和修改,但没有身份验证)。
$post_data = "Some xml here";
$soapUrl = "http://yoursite.com/soap.asmx"; // asmx URL of WSDL
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: http://yoursite.com/SOAPAction",
"Content-length: " . strlen($post_data),
); //SOAPAction: your op URL
$url = $soapUrl;
// PHP cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
/* Check for an error when processing the request. */
if(curl_errno($ch) != 0) {
// TODO handle the error
}
curl_close($ch);
// TODO Parse and process the $response variable (returned as XML)
回答by aravind
To your first question,
对于你的第一个问题,
What can I do to make this cross-domain request?
我该怎么做才能发出这个跨域请求?
The following request headers are first sent to the server. Based on the response headers, the UserAgent, i.e. browser here, will discard the response(if any) and not give it back to the XHR callback, when the headers don't add up.
以下请求头首先发送到服务器。根据响应标头,UserAgent,即此处的浏览器,将丢弃响应(如果有),并且不会将其返回给 XHR 回调,当标头不加时。
Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header
Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header
Your server should then respond with the following headers:
然后,您的服务器应使用以下标头进行响应:
Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: X-Custom-Header
Example taken from - https://stackoverflow.com/a/8689332/1304559
示例取自 - https://stackoverflow.com/a/8689332/1304559
You can use tools like Fiddler or Web Inspector Network tab(Chrome) or Firebug's network tab to find the headers the server is sending back in response to your request.
您可以使用 Fiddler 或 Web Inspector 网络选项卡(Chrome)或 Firebug 的网络选项卡等工具来查找服务器为响应您的请求而发回的标头。
The third party API server url should respond back with the supported values. If it doesn't that's your problem.
第三方 API 服务器 url 应使用支持的值进行响应。如果不是,那是你的问题。
Can't be of much help in JsonP 500 server error, as it says Internal Server Error
对 JsonP 500 服务器错误没有多大帮助,正如它所说的内部服务器错误
UPDATE
更新
I saw your screen shots, couple of things to notice here
我看到了你的屏幕截图,这里有几件事要注意
HTTP POST
is used- No
Access-Control
headers found in both modes response. With second status code as302
Origin
request header isnull
, so I believe the HTML file is opened from the file system rather than from a web site
HTTP POST
用来Access-Control
在两种模式响应中都找不到标头。第二个状态码为302
Origin
请求标头是null
,所以我相信 HTML 文件是从文件系统而不是从网站打开的
Enabling JSONP
启用 JSONP
Coming to the point of why JSONP is not working, reason - The web service config(of the ASMX specified), has not enabled GET
mode for the request. JSONP doesn't work with POST
.
谈到为什么 JSONP 不起作用,原因 - Web 服务配置(指定的 ASMX)尚未GET
为请求启用模式。JSONP 不适用于POST
.
Why 200
with security disabled?
为什么200
禁用安全?
The POST request is directly called with no OPTIONS
or preflight request fired before it, so server simply responds back.
POST 请求被直接调用,OPTIONS
在它之前没有触发或预检请求,因此服务器只是响应。
Why 302
status code with security enabled?
为什么302
启用安全的状态代码?
First a little on how it happens when security flag is not disabled(default). The OPTIONS
request is fired to the URL. The URL should respond back with a list of HTTP methods that can be used, i.e. GET
, POST
, etc. The status code of this OPTIONS
request should be 200
.
首先介绍一下当安全标志没有被禁用(默认)时它是如何发生的。该OPTIONS
请求被解雇的URL。URL应与可以使用HTTP方法,即清单进行回应GET
,POST
等这的状态代码OPTIONS
的请求应200
。
In the current case, there is a redirect called when doing this. And the redirect is pointing to a custom error handler for a HTTP Server Error. I believe it is 404
error, which is being caught and redirected.[This could be because the custom handler is set to ResponseRedirect
instead of ResponseRewrite
] The reason for the 404
is cross-domain access is not enabled.
在当前情况下,执行此操作时会调用重定向。并且重定向指向 HTTP 服务器错误的自定义错误处理程序。我相信这是404
错误,它被捕获并重定向。[这可能是因为自定义处理程序设置为ResponseRedirect
而不是ResponseRewrite
] 原因404
是未启用跨域访问。
In case the custom error handling was turned off, this would have returned HTTP 500
code. I believe the problem can be found by checking the server logs immediately after firing a cross-domain request. It will be good to check the server logs for errors other than this, if any.
如果自定义错误处理被关闭,这将返回HTTP 500
代码。我相信可以通过在触发跨域请求后立即检查服务器日志来发现问题。如果有的话,最好检查服务器日志是否有其他错误。
Possible solution
可能的解决方案
To enable access, there are two ways - detailed here. Or directly add the access control headers to web.config
file's customheaders
section.
要启用访问,有两种方法 -在此处详述。或者直接将访问控制头添加到web.config
文件的customheaders
部分。
When cross-domain access is enabled, the server should respond back to OPTIONS and allow the request to go through. This should return HTTP 200
unless there are other errors. But ajax callback will not be able to access the response. This can be done now only if Access-Control-Allow-Origin
is set to "*" or the Origin
request header value, and the Access-Control
as needed. And the ajax callback will receive the response as intended.
当启用跨域访问时,服务器应响应 OPTIONS 并允许请求通过。HTTP 200
除非有其他错误,否则应该返回。但是ajax回调将无法访问响应。现在仅当Access-Control-Allow-Origin
设置为“*”或Origin
请求标头值时才能完成此操作,并且Access-Control
根据需要。并且 ajax 回调将按预期接收响应。
The third point, null Origin
. This will be a problem if the Origin
request header value is sent back as Access-Control-Allow-Origin
. But I am assuming you will be moving your HTML page to a web server, so that shouldn't be a problem.
第三点, null Origin
。如果Origin
请求标头值作为Access-Control-Allow-Origin
. 但我假设您会将 HTML 页面移动到 Web 服务器,因此这应该不是问题。
Hope this helps!
希望这可以帮助!
回答by waki
You can use cURL ? With Ajax you send data to your handler (on your server, let called callback.php). In your file (callback.php) use cURL with your data:
您可以使用 cURL 吗?使用 Ajax,您可以将数据发送到您的处理程序(在您的服务器上,称为 callback.php)。在您的文件 (callback.php) 中,将 cURL 与您的数据一起使用:
$post_data = array(
'key' => 'key',
'test' => 'text'
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($curl, CURLOPT_URL, 'http://www.domain.com/');
$return = json_decode(trim(curl_exec($curl)), TRUE);
curl_close($curl);
in your $return variable you get your data.
在您的 $return 变量中,您可以获得数据。