Come ottenere una richiesta di condivisione di risorse di origine incrociata (CORS) funzionante

Ho una macchina sulla mia lan locale (machineA) che ha due server web. Il primo è quello incorporato in XBMC (sulla porta 8080) e visualizza la nostra libreria. Il secondo server è uno script Python CherryPy (porta 8081) che sto usando per triggersre una conversione di file su richiesta. La conversione del file viene triggersta da una richiesta POST AJAX dalla pagina servita dal server XBMC.

  • Vai a http: // machineA: 8080 che visualizza la libreria
  • La biblioteca è visualizzata
  • L’utente fa clic sul link “converti” che emette il seguente comando:

jQuery Ajax Request

$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)}) 
  • Il browser invia una richiesta HTTP OPTIONS con le seguenti intestazioni;

Intestazione richiesta – OPZIONI

 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 
  • Il server risponde con quanto segue;

Intestazione di risposta – OPZIONI (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 
  • La conversazione si interrompe. Il browser, in teoria, dovrebbe inviare una richiesta POST in quanto il server ha risposto con le intestazioni CORS corrette (?) (Access-Control-Allow-Origin: *)

Per la risoluzione dei problemi, ho anche emesso lo stesso comando $ .post da http://jquery.com . Qui è dove sono perplesso, da jquery.com, la richiesta di post funziona, una richiesta OPTIONS viene inviata seguendo un POST. Le intestazioni di questa transazione sono sotto;

Intestazione richiesta – OPZIONI

 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 

Intestazione di risposta – OPZIONI (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 

Intestazione richiesta – 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 

Intestazione di risposta – 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 

Non riesco a capire perché la stessa richiesta potrebbe funzionare da un sito, ma non dall’altra. Spero che qualcuno possa essere in grado di indicare cosa mi manca. Grazie per l’aiuto!

Alla fine mi sono imbattuto in questo link ” Una richiesta CORS POST funziona con un semplice javascript, ma perché no con jQuery? ” Che osserva che jQuery 1.5.1 aggiunge il

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

intestazione a tutte le richieste CORS. jQuery 1.5.2 non lo fa. Inoltre, in base alla stessa domanda, impostare un’intestazione di risposta del server di

 Access-Control-Allow-Headers: * 

non consente alla risposta di continuare. È necessario assicurarsi che l’intestazione di risposta includa specificamente le intestazioni richieste. vale a dire:

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

RICHIESTA:

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

RISPOSTA:

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

Mi ci è voluto un po ‘di tempo per trovare la soluzione.

Nel caso in cui la risposta del server sia corretta e la richiesta è il problema, è necessario aggiungere withCredentials: true agli xhrFields nella richiesta:

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

Nota: jQuery> = 1.5.1 è richiesto

Bene, ho lottato con questo problema per un paio di settimane.

Il modo più semplice, più rispettoso e non hacky per farlo è quello di utilizzare probabilmente un’API JavaScript provider che non effettua chiamate basate su browser e in grado di gestire le richieste di Cross Origin.

Ad esempio Facebook JavaScript API e Google JS API.

Nel caso in cui il tuo provider API non sia aggiornato e non supporti l’intestazione ‘Origine’ di Cross Origin Resource nella sua risposta e non abbia un API JS (Sì, sto parlando di te Yahoo), sei colpito con una delle tre opzioni-

  1. Usando jsonp nelle tue richieste che aggiunge una funzione di callback al tuo URL dove puoi gestire la tua risposta. Spiega che questo cambierà l’URL della richiesta in modo che il tuo server API debba essere equipaggiato per gestire il callback = alla fine dell’URL.

  2. Invia la richiesta al tuo server API che è il tuo controllore ed è nello stesso dominio del client o ha la Condivisione di risorse Cross Origin abilitata da dove puoi indirizzare la richiesta al server API di terze parti.

  3. Probabilmente più utile nei casi in cui stai facendo richieste OAuth e hai bisogno di gestire l’interazione dell’utente Haha! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')

Usando questo in combinazione con Laravel ho risolto il mio problema. Basta aggiungere questa intestazione alla richiesta jquery Access-Control-Request-Headers: x-requested-with e assicurarsi che la risposta lato server abbia questa intestazione set Access-Control-Allow-Headers: * .

Ho risolto il mio problema durante l’utilizzo dell’API distance matrix di google impostando l’intestazione della mia richiesta con Jquery ajax. dai un’occhiata qui sotto.

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

Nota cosa ho aggiunto alle impostazioni
**

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

**
Spero che aiuti.

Per qualche ragione, una domanda sulle richieste GET è stata unita a questa, quindi ti risponderò qui.

Questa semplice funzione riceve in modo asincrono una risposta di stato HTTP da una pagina abilitata per CORS. Se lo esegui, vedrai che solo una pagina con le intestazioni appropriate restituisce uno stato 200 se vi si accede tramite XMLHttpRequest, indipendentemente dall’utilizzo di GET o POST. Nulla può essere fatto sul lato client per aggirare questo tranne possibilmente utilizzando JSONP se hai solo bisogno di un object JSON.

Quanto segue può essere facilmente modificato per ottenere i dati contenuti nell’object 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"); } } } 
   Check if page is cors   

A CORS-enabled source has one of the following HTTP headers:

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

Click a button to see if the page allows CORS

Ho avuto lo stesso identico problema in cui jquery ajax mi ha dato solo problemi cors su richieste post in cui le richieste di ottenere funzionavano bene – ho stancato tutto senza risultati. Ho avuto le intestazioni corrette nel mio server ecc. Cambiare per usare XMLHTTPRequest invece di jquery ha corretto immediatamente il mio problema. Indipendentemente dalla versione di jquery che ho usato, non è stato risolto. Fetch funziona anche senza problemi se non hai bisogno di compatibilità con i browser a ritroso.

  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) 

Speriamo che questo aiuti chiunque altro con gli stessi problemi.

Questo è un riassunto di ciò che ha funzionato per me:

Definire una nuova funzione (avvolto $.ajax per semplificare):

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

Uso:

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

Funziona anche con .fail , .fail , ecc:

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

Lato server (in questo caso in cui example.com è ospitato), imposta queste intestazioni (aggiunto un codice di esempio 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); 

Questo è l’unico modo in cui conosco veramente il cross-domain POST da JS.

JSONP converte il POST in GET che può visualizzare informazioni sensibili sui log del server.

Questo è un po ‘tardi per la festa, ma ho lottato con questo per un paio di giorni. È ansible e nessuna delle risposte che ho trovato qui ha funzionato. È ingannevolmente semplice. Ecco la chiamata .ajax:

      Javascript Test