跨域AJAX请求无效

我在第三方API上调用POST,我一直在使用jQuery的$ .ajax函数。 但是,当我进行调用时,我收到以下错误: 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. 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.

我在这篇文章中看到这可能是一个Webkit错误,所以我在Firefox中尝试过它(我在Chrome中开发)并得到了相同的结果。我在Chrome和Firefox上尝试了这个,我得到了相同的结果。

根据这篇文章 ,我也尝试通过将$ .ajax函数的crossDomain属性设置为true并将dataType设置为jsonp来使用jsonp 。 但是,这导致500内部服务器错误。

当我使用–disable-web-security标志启动Chrome时,我没有任何问题。 但是,如果我正常启动浏览器,那么我会收到错误。

所以,我想这可能是一个由两部分组成的问题。 我该怎么做才能提出这个跨域请求? 如果JSONP是答案,那么我该如何确定第三方API是否设置正确以支持这一点?

编辑:这是我在禁用浏览器安全性的情况下拨打电话的屏幕截图: https : //drive.google.com/file/d/0Bzo7loNBQcmjUjk5YWNWLXM2SVE/edit?usp =sharing

这是我在启用浏览器安全性的情况下拨打电话时的屏幕截图(正常情况下): https ://drive.google.com/file/d/0Bzo7loNBQcmjam5NQ3BKWUluRE0/edit?usp=sharing

对于你的第一个问题,

我该怎么做才能提出这个跨域请求?

首先将以下请求标头发送到服务器。 根据响应标头,UserAgent(即此处的浏览器)将丢弃响应(如果有),并且当标头未加起来时不将其返回到XHR回调。

Origin: http://yourdomain.com Access-Control-Request-Method: POST Access-Control-Request-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

示例取自 – https://stackoverflow.com/a/8689332/1304559

您可以使用Fiddler或Web Inspector Network选项卡(Chrome)或Firebug的网络选项卡等工具查找服务器响应您的请求发回的标头。

第三方API服务器URL应使用支持的值进行响应。 如果不是那就是你的问题。

在JsonP 500服务器错误中没有多大帮助,因为它说内部服务器错误


UPDATE

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

  1. HTTP POST
  2. 两种模式响应中均未找到Access-Control标头。 第二个状态码为302
  3. Origin请求标头为null ,因此我认为HTML文件是从文件系统而不是从网站打开的

启用JSONP

为了说明为什么JSONP不起作用,原因 – Web服务配置(指定的ASMX)没有为请求启用GET模式。 JSONP不适用于POST

为什么200安全禁用?

直接调用POST请求时没有OPTIONS或preflight请求,因此服务器只会响应。

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

首先说明未禁用安全标志时的情况(默认)。 OPTIONS请求被触发到URL。 URL应该回复一个可以使用的HTTP方法列表,即GETPOST等。此OPTIONS请求的状态代码应该是200

在当前情况下,执行此操作时会调用重定向。 并且重定向指向HTTP服务器错误的自定义error handling程序。 我相信这是404错误,它被捕获并重定向。[这可能是因为自定义处理程序设置为ResponseRedirect而不是ResponseRewrite ] 404的原因是跨域访问未启用。

如果关闭自定义error handling,这将返回HTTP 500代码。 我相信通过在触发跨域请求后立即检查服务器日志可以找到问题。 最好检查服务器日志以查找除此之外的错误(如果有)。

可能的方案

要启用访问权限,有两种方法 – 详细说明 。 或者直接将访问控制头添加到web.config文件的customheaders部分。

启用跨域访问时,服务器应响应OPTIONS并允许请求通过。 除非存在其他错误,否则应返回HTTP 200 。 但是ajax回调将无法访问响应。 只有当Access-Control-Allow-Origin设置为“*”或Origin请求标头值,并且根据需要设置Access-Control ,才能执行此操作。 并且ajax回调将按预期收到响应。

第三点,null Origin 。 如果将Origin请求标头值作为Access-Control-Allow-Origin发回,则这将是一个问题。 但我假设您将HTML页面移动到Web服务器,所以这不应该是一个问题。

希望这可以帮助!

我想出的解决方案是使用cURL(如提及@waki),但是支持SOAP的略微修改版本。 然后,不是对第三方API(配置不正确)进行AJAX调用,而是调用我的本地PHP文件,然后对第三方API进行SOAP调用并将数据传递回我的PHP文件,我可以然后处理它。 这让我忘记了CORS以及与之相关的所有复杂性。 这是代码(从这个问题中获取和修改,但没有身份validation)。

 $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) 

你可以用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); 

在$ return变量中,您可以获得数据。