Hoe een cross-origin resource sharing (CORS) postverzoek werkend te krijgen

Ik heb een machine op mijn lokale lan (machineA) met twee webservers. De eerste is de ingebouwde in XBMC (op poort 8080) en geeft onze bibliotheek weer. De tweede server is een CherryPy-pythonscript (poort 8081) dat ik gebruik om een bestandsconversie op aanvraag te activeren. De bestandsconversie wordt geactiveerd door een AJAX POST-verzoek van de pagina die wordt aangeboden vanaf de XBMC-server.

  • Ga naar http://machineA:8080die bibliotheek weergeeft
  • Bibliotheek wordt weergegeven
  • Gebruiker klikt op de link ‘converteren’ die de volgende opdracht geeft –

jQuery Ajax-verzoek

$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
  • De browser geeft een HTTP OPTIONS-verzoek uit met de volgende headers;

Verzoek header – OPTIES

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
  • De server reageert met het volgende;

Reactiekop – OPTIES (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
  • Het gesprek stopt dan. De browser, zou in theorie moeten zijn, een postverzoek afgeven omdat de server reageerde met de juiste (?) CORS-headers (toegangscontrole-toestaan-oorsprong: *)

Voor het oplossen van problemen, heb ik ook dezelfde $ .post-opdracht uitgegeven van http://jquery.com . Dit is waar ik stumped, van JQuery.com, het postverzoek werkt, een optiesverzoek wordt door een bericht verzonden. De koppen van deze transactie staan ​​hieronder;

Aanvraag header – Opties

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

Response-header – Opties (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

Aanvraag header – 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

Reactiekop – 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

Ik begrijp niet waarom hetzelfde verzoek wel zou werken op de ene site, maar niet op de andere. Ik hoop dat iemand mij kan vertellen wat ik mis. Bedankt voor je hulp!


Antwoord 1, autoriteit 100%

Eindelijk stuitte ik op deze link “Een CORS POST-verzoek werkt vanuit gewoon javascript, maar waarom niet met jQuery?” waarin wordt opgemerkt dat jQuery 1.5.1 de

toevoegt

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

header voor alle CORS-verzoeken. jQuery 1.5.2 doet dit niet. Ook, volgens dezelfde vraag, het instellen van een serverresponsheader van

Access-Control-Allow-Headers: *

staat niet toe dat de reactie wordt voortgezet. U moet ervoor zorgen dat de antwoordheader specifiek de vereiste headers bevat. dat wil zeggen:

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

Antwoord 2, autoriteit 43%

VERZOEK:

$.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");
            }
        });

RESPONS:

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

Antwoord 3, autoriteit 14%

Ik heb mijn eigen probleem opgelost bij het gebruik van de Google Distance Matrix API door mijn verzoekheader in te stellen met JQuery ajax. kijk hieronder.

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);
      });

Let op wat ik heb toegevoegd bij de instellingen
**

"headers": {
          "accept": "application/json",
          "Access-Control-Allow-Origin":"*"
      }

**
Ik hoop dat dit helpt.


Antwoord 4, autoriteit 8%

Het kostte me wat tijd om de oplossing te vinden.

In het geval dat uw serverantwoord correct is en het verzoek het probleem is, moet u withCredentials: truetoevoegen aan de xhrFieldsin het verzoek:

$.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
    }
});

Opmerking: jQuery >= 1.5.1 is vereist


Antwoord 5, autoriteit 5%

Nou, ik heb een paar weken met dit probleem geworsteld.

De gemakkelijkste, meest compatibele en niet-hacky manier om dit te doen, is door waarschijnlijk een JavaScript-API van een provider te gebruiken die geen browsergebaseerde aanroepen doet en Cross Origin-verzoeken kan verwerken.

Bijvoorbeeld Facebook JavaScript API en Google JS API.

In het geval dat uw API-provider niet actueel is en Cross Origin Resource Origin ‘*’-header niet ondersteunt in zijn antwoord en geen JS-api heeft (Ja, ik heb het over u Yahoo), wordt u getroffen door een van de drie opties-

  1. Jsonp gebruiken in uw verzoeken die een callback-functie aan uw URL toevoegt waar u uw reactie kunt verwerken.
    Waarschuwing: dit zal de verzoek-URL veranderen, zodat uw API-server moet zijn uitgerust om de ?callback= aan het einde van de URL te verwerken.

  2. Stuur het verzoek naar uw API-server die door u wordt beheerd en die zich in hetzelfde domein als de client bevindt of Cross Origin Resource Sharing heeft ingeschakeld van waaruit u het verzoek kunt proxyen naar de API-server van derden.

  3. Waarschijnlijk het handigst in gevallen waarin u OAuth-verzoeken doet en gebruikersinteractie moet afhandelen Haha! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')


Antwoord 6, autoriteit 2%

Het gebruik hiervan in combinatie met Laravel loste mijn probleem op. Voeg deze header toe aan uw jQuery-verzoek Access-Control-Request-Headers: x-requested-withen zorg ervoor dat uw server-side antwoord deze header heeft Access-Control-Allow-Headers: *.


Antwoord 7, autoriteit 2%

Dit is een samenvatting van wat voor mij werkte:

Definieer een nieuwe functie (verpakt $.ajaxom te vereenvoudigen):

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({}) 
    }
  });
}

Gebruik:

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

Werkt ook met .done,.fail,etc:

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

Serverzijde (in dit geval waar example.com wordt gehost), stel deze headers in (een voorbeeldcode toegevoegd in 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);

Dit is de enige manier die ik ken om echt cross-domein te POST vanuit JS.

JSONP converteert de POST naar GET die gevoelige informatie kan weergeven in serverlogboeken.


Antwoord 8

Om de een of andere reden is een vraag over GET-verzoeken samengevoegd met deze, dus ik zal deze hier beantwoorden.

Deze eenvoudige functie krijgt asynchroon een HTTP-statusantwoord van een CORS-compatibele pagina. Als je het uitvoert, zul je zien dat alleen een pagina met de juiste headers een 200-status retourneert als deze wordt geopend via XMLHttpRequest – of GET of POST wordt gebruikt. Er kan aan de clientzijde niets worden gedaan om dit te omzeilen, behalve mogelijk het gebruik van JSONP als je alleen een json-object nodig hebt.

Het volgende kan eenvoudig worden gewijzigd om de gegevens in het xmlHttpRequestObject-object te krijgen:

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>

Antwoord 9

Ik had exact hetzelfde probleem waarbij jquery ajax me alleen cors-problemen gaf bij postverzoeken waarbij get-verzoeken prima werkten – ik was alles hierboven moe zonder resultaat. Ik had de juiste headers op mijn server enz. Door over te schakelen naar XMLHTTPRequest in plaats van jQuery, werd mijn probleem onmiddellijk opgelost. Welke versie van jQuery ik ook gebruikte, het loste het niet op. Fetch werkt ook zonder problemen als je geen achterwaartse browsercompatibiliteit nodig hebt.

       var xhr = new XMLHttpRequest()
        xhr.open('POST', 'https://mywebsite.com', true)
        xhr.withCredentials = true
        xhr.onreadystatechange = function() {
          if (xhr.readyState === 2) {// do something}
        }
        xhr.setRequestHeader('Content-Type', 'application/json')
        xhr.send(json)

Hopelijk helpt dit iemand anders met dezelfde problemen.


Antwoord 10

Als je om de een of andere reden nog steeds niets bereikt terwijl je probeert headers toe te voegen of controlebeleid in te stellen, kun je overwegen om apache ProxyPass te gebruiken…

Bijvoorbeeld in een <VirtualHost>die SSL gebruikt, voeg je de twee volgende instructies toe:

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

Zorg ervoor dat de volgende apache-modules zijn geladen (laad ze met a2enmod):

  • proxy
  • proxy_connect
  • proxy_http

Het is duidelijk dat u de URL van uw AJAX-verzoeken moet wijzigen om de apache-proxy te gebruiken…


Antwoord 11

Dit is een beetje laat voor het feest, maar ik worstel hier al een paar dagen mee. Het is mogelijk en geen van de antwoorden die ik hier heb gevonden heeft gewerkt. Het is bedrieglijk eenvoudig.
Hier is de .ajax-oproep:

   <!DOCTYPE HTML>
    <html>
    <head>
    <body>
     <title>Javascript Test</title>
     <script src="https://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='[email protected]'",
        success: function (data) {
           alert(data);
        },
        error: function (x, y, z) {
           alert(x.responseText + " :EEE: " + x.status);
        }
    });
    });
    </script> 
    </body>
    </html>

Other episodes