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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 01:55:46  来源:igfitidea点击:

Cross-domain AJAX request not working

jqueryajaxcross-domainjsonpcors

提问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 crossDomainproperty of the $.ajax function to trueand setting the dataTypeto 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

我看到了你的屏幕截图,这里有几件事要注意

  1. HTTP POSTis used
  2. No Access-Controlheaders found in both modes response. With second status code as 302
  3. Originrequest header is null, so I believe the HTML file is opened from the file system rather than from a web site
  1. HTTP POST用来
  2. Access-Control在两种模式响应中都找不到标头。第二个状态码为302
  3. 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 GETmode for the request. JSONP doesn't work with POST.

谈到为什么 JSONP 不起作用,原因 - Web 服务配置(指定的 ASMX)尚未GET为请求启用模式。JSONP 不适用于POST.

Why 200with security disabled?

为什么200禁用安全?

The POST request is directly called with no OPTIONSor preflight request fired before it, so server simply responds back.

POST 请求被直接调用,OPTIONS在它之前没有触发或预检请求,因此服务器只是响应。

Why 302status code with security enabled?

为什么302启用安全的状态代码?

First a little on how it happens when security flag is not disabled(default). The OPTIONSrequest 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 OPTIONSrequest should be 200.

首先介绍一下当安全标志没有被禁用(默认)时它是如何发生的。该OPTIONS请求被解雇的URL。URL应与可以使用HTTP方法,即清单进行回应GETPOST等这的状态代码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 404error, which is being caught and redirected.[This could be because the custom handler is set to ResponseRedirectinstead of ResponseRewrite] The reason for the 404is 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 500code. 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.configfile's customheaderssection.

要启用访问,有两种方法 -在此处详述。或者直接将访问控制头添加到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 200unless 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-Originis set to "*" or the Originrequest header value, and the Access-Controlas 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 Originrequest 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 变量中,您可以获得数据。