如何获得跨源资源共享(CORS)的后期请求工作

我有一台机器在我的本地局域网(machineA)有两个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确定)

 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 
  • 谈话然后停止。 浏览器在理论上应该发出POST请求,因为服务器用正确的(?)CORS头(Access-Control-Allow-Origin:*)

为了排除故障,我也从http://jquery.com发出了相同的$ .post命令。 这是我被困在从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确定)

 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(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 

我无法弄清楚为什么相同的请求会在一个站点上运行,而不是在另一个站点上运行。 我希望有人能够指出我缺less的东西。 谢谢你的帮助!

我终于偶然发现了这个链接“ 一个CORS POST请求从普通的javascript工作,但为什么不与jQuery? ”,指出,jQuery 1.5.1添加

  Access-Control-Request-Headers: x-requested-with 

头到所有CORS请求。 jQuery 1.5.2不这样做。 另外,根据同样的问题,设置一个服务器响应头

 Access-Control-Allow-Headers: * 

不允许响应继续。 您需要确保响应头特别包含所需的头文件。 即:

 Access-Control-Allow-Headers: x-requested-with 

请求:

  $.ajax({ url: "http://localhost:8079/students/add/", type: "POST", crossDomain: true, data: JSON.stringify(somejson), dataType: "json", success: function (response) { var resp = JSON.parse(response) alert(resp.status); }, error: function (xhr, status) { alert("error"); } }); 

响应:

 response = HttpResponse(json.dumps('{"status" : "success"}')) response.__setitem__("Content-type", "application/json") response.__setitem__("Access-Control-Allow-Origin", "*") return response 

那么我在这个问题上挣扎了几个星期。

最简单,最合规,最不危险的方法就是使用提供者JavaScript API,它不会创build基于浏览器的调用,并且可以处理跨源请求。

例如Facebook JavaScript API和Google JS API。

如果您的API提供程序不是最新的,并且在响应中不支持跨源资源源*的标头,并且没有JS api(是的,我正在谈论您的雅虎),您将遇到以下三个选项之一 –

  1. 在您的请求中使用jsonp,在您的URL中添加callback函数,以便处理您的响应。 注意这将改变请求的URL,所以你的API服务器必须配备来处理URL后面的?callback =。

  2. 将请求发送到由您控制的API服务器,并且与客户端位于同一个域中,或者启用了跨域资源共享,您可以将请求代理到第三方API服务器。

  3. 可能最有用的情况下,你正在做OAuth请求,需要处理用户交互哈哈! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')

花了一些时间find解决scheme。

如果你的服务器响应正确,请求是问题,你应该添加withCredentials: true请求中的xhrFields

 $.ajax({ url: url, type: method, // This is the important part xhrFields: { withCredentials: true }, // This is the important part data: data, success: function (response) { // handle the response }, error: function (xhr, status) { // handle errors } }); 

注意:jQuery> = 1.5.1是必需的

与Laravel结合使用解决了我的问题。 只需将此头添加到您的jquery请求Access-Control-Request-Headers: x-requested-with并确保您的服务器端响应具有此头设置Access-Control-Allow-Headers: *

这是对我有用的一个总结:

定义一个新的函数(包装$.ajax来简化):

 jQuery.postCORS = function(url, data, func) { if(func == undefined) func = function(){}; return $.ajax({ type: 'POST', url: url, data: data, dataType: 'json', contentType: 'application/x-www-form-urlencoded', xhrFields: { withCredentials: true }, success: function(res) { func(res) }, error: function() { func({}) }}); } 

用法:

 $.postCORS("https://example.com/service.json",{ x : 1 },function(obj){ if(obj.ok) { ... } }); 

也适用于.done.fail等:

 $.postCORS("https://example.com/service.json",{ x : 1 }).done(function(obj){ if(obj.ok) { ... } }).fail(function(){ alert("Error!"); }); 

服务器端(在这种情况下,example.com托pipe),设置这些头(在PHP中添加一些示例代码):

 header('Access-Control-Allow-Origin: https://not-example.com'); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Max-Age: 604800'); header("Content-type: application/json"); $array = array("ok" => $_POST["x"]); echo json_encode($array); 

这是我知道从JS真正开启跨域的唯一途径。

JSONP将POST转换为GET,这可能会在服务器日志中显示敏感信息。

出于某种原因,有关GET请求的问题与这个合并,所以我会在这里回应。

这个简单的函数将asynchronous地从启用CORS的页面获取HTTP状态回复。 如果你运行它,你会发现如果通过XMLHttpRequest进行访问,只有具有正确头文件的页面返回200状态 – 无论是使用GET还是POST。 除了可能使用JSONP,如果你只需要一个JSON对象,客户端可以做任何事情来解决这个问题。

以下内容可以很容易地修改,以获取保存在xmlHttpRequestObject对象中的数据:

 function checkCorsSource(source) { var xmlHttpRequestObject; if (window.XMLHttpRequest) { xmlHttpRequestObject = new XMLHttpRequest(); if (xmlHttpRequestObject != null) { var sUrl = ""; if (source == "google") { var sUrl = "https://www.google.com"; } else { var sUrl = "https://httpbin.org/get"; } document.getElementById("txt1").innerHTML = "Request Sent..."; xmlHttpRequestObject.open("GET", sUrl, true); xmlHttpRequestObject.onreadystatechange = function() { if (xmlHttpRequestObject.readyState == 4 && xmlHttpRequestObject.status == 200) { document.getElementById("txt1").innerHTML = "200 Response received!"; } else { document.getElementById("txt1").innerHTML = "200 Response failed!"; } } xmlHttpRequestObject.send(); } else { window.alert("Error creating XmlHttpRequest object. Client is not CORS enabled"); } } } 
 <html> <head> <title>Check if page is cors</title> </head> <body> <p>A CORS-enabled source has one of the following HTTP headers:</p> <ul> <li>Access-Control-Allow-Headers: *</li> <li>Access-Control-Allow-Headers: x-requested-with</li> </ul> <p>Click a button to see if the page allows CORS</p> <form name="form1" action="" method="get"> <input type="button" name="btn1" value="Check Google Page" onClick="checkCorsSource('google')"> <input type="button" name="btn1" value="Check Cors Page" onClick="checkCorsSource('cors')"> </form> <p id="txt1" /> </body> </html> 

晚会有点晚,但是我一直在挣扎几天。 这是可能的,没有我在这里find的答案已经工作。 这看起来很简单。 这里是.ajax调用:

  <!DOCTYPE HTML> <html> <head> <body> <title>Javascript Test</title> <script src="jquery-1.11.1.min.js"></script> <script type="text/javascript"> $(document).domain = 'XXX.com'; $(document).ready(function () { $.ajax({ xhrFields: {cors: false}, type: "GET", url: "http://XXXX.com/test.php?email='steve@XXX.com'", success: function (data) { alert(data); }, error: function (x, y, z) { alert(x.responseText + " :EEE: " + x.status); } }); }); </script> </body> </html>