如何通过JavaScript发送跨域POST请求?

注释-它不应该刷新页面,然后我需要抓取并解析响应。


当前回答

如果您可以访问所有相关的服务器,请在另一个域请求的页面的回复标题中放入以下内容:

PHP:

header('Access-Control-Allow-Origin: *');

例如,在Drupal的xmlrpc.php代码中,你会这样做:

function xmlrpc_server_output($xml) {
    $xml = '<?xml version="1.0"?>'."\n". $xml;
    header('Connection: close');
    header('Content-Length: '. strlen($xml));
    header('Access-Control-Allow-Origin: *');
    header('Content-Type: application/x-www-form-urlencoded');
    header('Date: '. date('r'));
    // $xml = str_replace("\n", " ", $xml); 

    echo $xml;
    exit;
}

这可能会产生安全问题,您应该确保采取了适当的措施来验证请求。

其他回答

检查http://taiyolab.com/mbtweet/scripts/twitterapi_call.js中的post_method函数——这是上面描述的iframe方法的一个很好的例子。

高水平……您需要在服务器上设置cname,以便other-ser.your-server.com指向other-server.com。

您的页面动态地创建了一个不可见的iframe,它充当您到other-server.com的传输。然后,您必须通过JS从您的页面与other-server.com通信,并使用回调将数据返回到您的页面。

可能,但需要your-server.com和other-server.com的协调

CORS是为你准备的。 CORS是“跨域资源共享”,是一种发送跨域请求的方式。现在XMLHttpRequest2和Fetch API都支持CORS,它可以发送POST和GET请求

但它也有局限性。服务器需要指定Access-Control-Allow-Origin,不能设置为“*”。

如果你想要任何origin都可以发送请求给你,你需要JSONP(也需要设置Access-Control-Allow-Origin,但可以是'*')

对于很多请求方式,如果你不知道如何选择,我认为你需要一个完整的功能组件来做到这一点。让我介绍一个简单的组件https://github.com/Joker-Jelly/catta


如果你正在使用现代浏览器(> IE9, Chrome, FF, Edge等),非常建议你使用一个简单但美丽的组件https://github.com/Joker-Jelly/catta.It没有依赖,小于3KB,它支持Fetch, AJAX和JSONP与相同致命的示例语法和选项。

catta('./data/simple.json').then(function (res) {
  console.log(res);
});

它还支持所有方式导入到您的项目,如ES6模块,CommonJS,甚至HTML中的<script>。

这是一个老问题,但一些新技术可能会帮助人们解决这个问题。

如果你有对其他服务器的管理访问权限,那么你可以使用开源Forge项目来完成你的跨域POST。Forge提供了一个跨域JavaScript XmlHttpRequest包装器,它利用了Flash的原始套接字API。POST甚至可以通过TLS完成。

您需要对您要发布的服务器进行管理访问的原因是,您必须提供一个跨域策略,允许从您的域进行访问。

http://github.com/digitalbazaar/forge

更新:在继续之前,每个人都应该阅读并理解html5rocks关于CORS的教程。它很容易理解,也很清楚。

如果您控制被post的服务器,只需通过在服务器上设置响应头来利用“跨源资源共享标准”。这个答案在本帖的其他答案中讨论过,但在我看来不是很清楚。

简而言之,下面是如何完成从from.com/1.html到to.com/postHere.php的跨域POST(以PHP为例)。注意:你只需要为NON OPTIONS请求设置Access-Control-Allow-Origin -这个例子总是为一个较小的代码片段设置所有的头部。

In postHere.php setup the following: switch ($_SERVER['HTTP_ORIGIN']) { case 'http://from.com': case 'https://from.com': header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']); header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS'); header('Access-Control-Max-Age: 1000'); header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With'); break; } This allows your script to make cross domain POST, GET and OPTIONS. This will become clear as you continue to read... Setup your cross domain POST from JS (jQuery example): $.ajax({ type: 'POST', url: 'https://to.com/postHere.php', crossDomain: true, data: '{"some":"json"}', dataType: 'json', success: function(responseData, textStatus, jqXHR) { var value = responseData.someKey; }, error: function (responseData, textStatus, errorThrown) { alert('POST failed.'); } });

When you do the POST in step 2, your browser will send a "OPTIONS" method to the server. This is a "sniff" by the browser to see if the server is cool with you POSTing to it. The server responds with an "Access-Control-Allow-Origin" telling the browser its OK to POST|GET|ORIGIN if request originated from "http://from.com" or "https://from.com". Since the server is OK with it, the browser will make a 2nd request (this time a POST). It is good practice to have your client set the content type it is sending - so you'll need to allow that as well.

MDN有一篇关于HTTP访问控制的文章,详细介绍了整个流程是如何工作的。根据他们的文档,它应该“在支持跨站XMLHttpRequest的浏览器中工作”。这有点误导,然而,因为我认为只有现代浏览器允许跨域POST。我只验证了这适用于safari,chrome,FF 3.6。

如果你这样做,请记住以下几点:

Your server will have to handle 2 requests per operation You will have to think about the security implications. Be careful before doing something like 'Access-Control-Allow-Origin: *' This wont work on mobile browsers. In my experience they do not allow cross domain POST at all. I've tested android, iPad, iPhone There is a pretty big bug in FF < 3.6 where if the server returns a non 400 response code AND there is a response body (validation errors for example), FF 3.6 wont get the response body. This is a huge pain in the ass, since you cant use good REST practices. See bug here (its filed under jQuery, but my guess is its a FF bug - seems to be fixed in FF4). Always return the headers above, not just on OPTION requests. FF needs it in the response from the POST.