如何使跨域资源共享(CORS)发布请求正常工作

Jam*_*mes 201 ajax jquery cherrypy cors

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

jQuery Ajax请求

$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
Run Code Online (Sandbox Code Playgroud)
  • 浏览器发出带有以下标头的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
Run Code Online (Sandbox Code Playgroud)
  • 服务器响应以下内容;

响应标题 - 选项(状态= 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
Run Code Online (Sandbox Code Playgroud)
  • 谈话然后停止.理论上,浏览器应该发出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
Run Code Online (Sandbox Code Playgroud)

响应标题 - 选项(状态= 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
Run Code Online (Sandbox Code Playgroud)

请求标题 - 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
Run Code Online (Sandbox Code Playgroud)

响应标头 - 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
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*mes 147

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

 Access-Control-Request-Headers: x-requested-with
Run Code Online (Sandbox Code Playgroud)

所有CORS请求的标头.jQuery 1.5.2没有这样做.另外,根据同样的问题,设置服务器响应头

Access-Control-Allow-Headers: *
Run Code Online (Sandbox Code Playgroud)

不允许继续响应.您需要确保响应标头具体包含所需的标头.即:

Access-Control-Allow-Headers: x-requested-with 
Run Code Online (Sandbox Code Playgroud)


Has*_*eer 63

请求:

 $.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");
            }
        });
Run Code Online (Sandbox Code Playgroud)

响应:

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

return response
Run Code Online (Sandbox Code Playgroud)

  • jsonp不适用于POST请求 (24认同)
  • 如果服务器不接受交叉原点,则crossdomain = true不必解决问题.使用dataType:"jsonp"并像jsonpCallback一样设置回调:"response"将是更好的主意.另见:http://api.jquery.com/jquery.ajax/ (3认同)

Dek*_*kel 12

花了一些时间找到解决方案.

在正常情况下,您的服务器响应和请求的问题,您应该添加withCredentials: truexhrFields在请求:

$.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
    }
});
Run Code Online (Sandbox Code Playgroud)

注意:jQuery> = 1.5.1是必需的


小智 9

好吧,我在这个问题上挣扎了几个星期.

最简单,最顺从和非hacky的方法是使用提供程序JavaScript API,它不会进行基于浏览器的调用,并且可以处理Cross Origin请求.

例如Facebook JavaScript API和Google JS API.

如果您的API提供程序不是最新的,并且在其响应中不支持Cross Origin Resource Origin'*'标头,并且没有JS api(是的,我在谈论您的Yahoo),您会被三个选项之一所震惊 -

  1. 在您的请求中使用jsonp,它会在您的URL中添加回调函数,您可以在其中处理响应.请注意,这将更改请求URL,因此您的API服务器必须配备以处理URL末尾的?callback =.

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

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


Mir*_*ool 8

我通过使用Jquery ajax设置请求标头来解决使用Google距离矩阵API时遇到的问题。看看下面。

var settings = {
          'cache': false,
          'dataType': "jsonp",
          "async": true,
          "crossDomain": true,
          "url": "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=place_id:"+me.originPlaceId+"&destinations=place_id:"+me.destinationPlaceId+"&region=ng&units=metric&key=mykey",
          "method": "GET",
          "headers": {
              "accept": "application/json",
              "Access-Control-Allow-Origin":"*"
          }
      }

      $.ajax(settings).done(function (response) {
          console.log(response);

      });
Run Code Online (Sandbox Code Playgroud)

注意我在设置中添加的内容
**

"headers": {
          "accept": "application/json",
          "Access-Control-Allow-Origin":"*"
      }
Run Code Online (Sandbox Code Playgroud)

**
我希望这会有所帮助。

  • 设置 dataType: "jsonp" 解决了我的问题 (4认同)
  • @Timsta,很高兴我的建议对您有用。也感谢堆栈溢出。祝你有美好的一天。 (3认同)

lep*_*epe 7

这是对我有用的总结:

定义一个新函数(包装$.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({}) 
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

用法:

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

也适用于.done.fail等:

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

服务器端(在本例中为 example.com 托管),设置这些标头(在 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);
Run Code Online (Sandbox Code Playgroud)

这是我所知道的真正从 JS 跨域 POST 的唯一方法。

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