我在本地局域网(machineA)上有一台机器,它有两个web服务器。第一个是XBMC中的内置程序(在端口8080上),它显示我们的库。第二个服务器是一个CherryPy python脚本(端口8081),我用它按需触发文件转换。文件转换由XBMC服务器提供的页面的AJAX POST请求触发。

转到http://machineA:8080,显示库 显示Library。 用户单击“转换”链接,发出以下命令-

jQuery Ajax请求

$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})

浏览器发出一个带有以下报头的HTTP OPTIONS请求;

请求头- 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

服务器响应如下;

响应头- 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

然后谈话就停止了。理论上,浏览器应该在服务器响应正确的(?)时发出POST请求。CORS报头(Access-Control-Allow-Origin: *)

为了排除故障,我还发布了相同的$。从http://jquery.com发布命令。这就是我难住的地方,从jquery.com, post请求工作,OPTIONS请求被post发送。来自该事务的标题如下;

请求头- 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

响应头- 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

请求头- 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

我不明白为什么同样的请求在一个站点上可以工作,而在另一个站点上就不行。我希望有人能指出我错过了什么。谢谢你的帮助!


当前回答

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

其他回答

这有点晚了,但我已经为此挣扎了好几天了。这是有可能的,我在这里找到的答案都不奏效。这看似简单。 下面是.ajax调用:

<!DOCTYPE HTML> <html> <head> <body> <title>Javascript Test</title> <script src="http://code.jquery.com/jquery-latest.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>

下面是服务器端的php:

<html> <head> <title>PHP Test</title> </head> <body> <?php header('Origin: xxx.com'); header('Access-Control-Allow-Origin:*'); $servername = "sqlxxx"; $username = "xxxx"; $password = "sss"; $conn = new mysqli($servername, $username, $password); if ($conn->connect_error) { die( "Connection failed: " . $conn->connect_error); } $sql = "SELECT email, status, userdata FROM msi.usersLive"; $result = $conn->query($sql); if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo $row["email"] . ":" . $row["status"] . ":" . $row["userdata"] . "<br>"; } } else { echo "{ }"; } $conn->close(); ?> </body>

如果由于某些原因,在尝试添加报头或设置控制策略时,你仍然没有得到任何地方,你可以考虑使用apache ProxyPass…

例如,在一个使用SSL的<VirtualHost>中添加以下两个指令:

SSLProxyEngine On
ProxyPass /oauth https://remote.tld/oauth

确保加载了以下apache模块(使用a2enmod加载它们):

代理 proxy_connect proxy_http

显然,为了使用apache代理,你必须改变你的AJAX请求url…

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

要求:

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

此函数将从启用cors的页面异步获取HTTP状态应答。如果通过XMLHttpRequest访问,只有具有正确标题的页面才会返回200状态——无论是使用GET还是POST。如果您只需要一个json对象,除了使用JSONP之外,在客户端无法解决这个问题。

可以修改以下内容以获得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>