How do I send a cross-domain POST request via JavaScript?

后端 未结 17 2385
说谎
说谎 2020-11-21 05:06

How do I send a cross-domain POST request via JavaScript?

Notes - it shouldn\'t refresh the page, and I need to grab and parse the response afterwards.

相关标签:
17条回答
  • 2020-11-21 05:59

    Update: Before continuing everyone should read and understand the html5rocks tutorial on CORS. It is easy to understand and very clear.

    If you control the server being POSTed, simply leverage the "Cross-Origin Resource Sharing standard" by setting response headers on the server. This answer is discussed in other answers in this thread, but not very clearly in my opinion.

    In short here is how you accomplish the cross domain POST from from.com/1.html to to.com/postHere.php (using PHP as an example). Note: you only need to set Access-Control-Allow-Origin for NON OPTIONS requests - this example always sets all headers for a smaller code snippet.

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

    2. 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 has a great write-up about HTTP access control, that goes into detail of how the entire flow works. According to their docs, it should "work in browsers that support cross-site XMLHttpRequest". This is a bit misleading however, as I THINK only modern browsers allow cross domain POST. I have only verified this works with safari,chrome,FF 3.6.

    Keep in mind the following if you do this:

    1. Your server will have to handle 2 requests per operation
    2. You will have to think about the security implications. Be careful before doing something like 'Access-Control-Allow-Origin: *'
    3. This wont work on mobile browsers. In my experience they do not allow cross domain POST at all. I've tested android, iPad, iPhone
    4. 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).
    5. Always return the headers above, not just on OPTION requests. FF needs it in the response from the POST.
    0 讨论(0)
  • 2020-11-21 06:00

    This is an old question, but some new technology might help someone out.

    If you have administrative access to the other server then you can use the opensource Forge project to accomplish your cross-domain POST. Forge provides a cross-domain JavaScript XmlHttpRequest wrapper that takes advantage of Flash's raw socket API. The POST can even be done over TLS.

    The reason you need administrative access to the server you are POSTing to is because you must provide a cross-domain policy that permits access from your domain.

    http://github.com/digitalbazaar/forge

    0 讨论(0)
  • 2020-11-21 06:01

    If you control the remote server, you should probably use CORS, as described in this answer; it's supported in IE8 and up, and all recent versions of FF, GC, and Safari. (But in IE8 and 9, CORS won't allow you to send cookies in the request.)

    So, if you don't control the remote server, or if you have to support IE7, or if you need cookies and you have to support IE8/9, you'll probably want to use an iframe technique.

    1. Create an iframe with a unique name. (iframes use a global namespace for the entire browser, so pick a name that no other website will use.)
    2. Construct a form with hidden inputs, targeting the iframe.
    3. Submit the form.

    Here's sample code; I tested it on IE6, IE7, IE8, IE9, FF4, GC11, S5.

    function crossDomainPost() {
      // Add the iframe with a unique name
      var iframe = document.createElement("iframe");
      var uniqueString = "CHANGE_THIS_TO_SOME_UNIQUE_STRING";
      document.body.appendChild(iframe);
      iframe.style.display = "none";
      iframe.contentWindow.name = uniqueString;
    
      // construct a form with hidden inputs, targeting the iframe
      var form = document.createElement("form");
      form.target = uniqueString;
      form.action = "http://INSERT_YOUR_URL_HERE";
      form.method = "POST";
    
      // repeat for each parameter
      var input = document.createElement("input");
      input.type = "hidden";
      input.name = "INSERT_YOUR_PARAMETER_NAME_HERE";
      input.value = "INSERT_YOUR_PARAMETER_VALUE_HERE";
      form.appendChild(input);
    
      document.body.appendChild(form);
      form.submit();
    }
    

    Beware! You won't be able to directly read the response of the POST, since the iframe exists on a separate domain. Frames aren't allowed to communicate with each other from different domains; this is the same-origin policy.

    If you control the remote server but you can't use CORS (e.g. because you're on IE8/IE9 and you need to use cookies), there are ways to work around the same-origin policy, for example by using window.postMessage and/or one of a number of libraries allowing you to send cross-domain cross-frame messages in older browsers:

    • Porthole
    • XSSInterface
    • EasyXDM
    • jQuery PostMessage Plugin

    If you don't control the remote server, then you can't read the response of the POST, period. It would cause security problems otherwise.

    0 讨论(0)
  • 2020-11-21 06:05

    CORS is for you. CORS is "Cross Origin Resource Sharing", is a way to send cross domain request.Now the XMLHttpRequest2 and Fetch API both support CORS, and it can send both POST and GET request

    But it has its limits.Server need to specific claim the Access-Control-Allow-Origin, and it can not be set to '*'.

    And if you want any origin can send request to you, you need JSONP (also need to set Access-Control-Allow-Origin, but can be '*')

    For lots of request way if you don't know how to choice, I think you need a full functional component to do that.Let me introduce a simple component https://github.com/Joker-Jelly/catta


    If you are using modern browser (> IE9, Chrome, FF, Edge, etc.), Very Recommend you to use a simple but beauty component https://github.com/Joker-Jelly/catta.It have no dependence, Less than 3KB, and it support Fetch, AJAX and JSONP with same deadly sample syntax and options.

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

    It also it support all the way to import to your project, like ES6 module, CommonJS and even <script> in HTML.

    0 讨论(0)
  • 2020-11-21 06:08

    High level.... You need to have a cname setup on your server so that other-serve.your-server.com points to other-server.com.

    Your page dynamically creates an invisible iframe, which acts as your transport to other-server.com. You then have to communicate via JS from your page to the other-server.com and have call backs that return the data back to your page.

    Possible but requires coordination from your-server.com and other-server.com

    0 讨论(0)
提交回复
热议问题