Como obter um trabalho de compartilhamento de resources de origem cruzada (CORS) após a solicitação

Eu tenho uma máquina na minha lan local (machineA) que tem dois servidores web. O primeiro é o embutido no XBMC (na porta 8080) e exibe nossa biblioteca. O segundo servidor é um script python CherryPy (porta 8081) que estou usando para acionar uma conversão de arquivo sob demanda. A conversão do arquivo é acionada por uma solicitação AJAX POST da página servida do servidor XBMC.

  • Ir para http: // machineA: 8080 que exibe a biblioteca
  • Biblioteca é exibida
  • O usuário clica no link ‘converter’ que emite o seguinte comando –

jQuery Ajax Request

$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)}) 
  • O navegador emite uma solicitação HTTP OPTIONS com os seguintes headers;

Cabeçalho de Solicitação – OPÇÕES

 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 
  • O servidor responde com o seguinte;

Cabeçalho de Resposta – OPÇÕES (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 
  • A conversa então pára. O navegador, em teoria, deve emitir uma solicitação POST conforme o servidor responde com os headers corretos CORS (Access-Control-Allow-Origin: *)

Para resolução de problemas, também emiti o mesmo comando $ .post de http://jquery.com . Este é o lugar onde estou perplexo, a partir de jquery.com, a solicitação post funciona, uma solicitação OPTIONS é enviada seguindo por um POST. Os headers dessa transação estão abaixo;

Cabeçalho de Solicitação – OPÇÕES

 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 

Cabeçalho de Resposta – OPÇÕES (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 

Cabeçalho de solicitação – 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 

Cabeçalho de Resposta – 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 

Eu não posso descobrir porque o mesmo pedido funcionaria de um site, mas não do outro. Espero que alguém possa apontar o que estou perdendo. Obrigado pela ajuda!

Eu finalmente deparei com este link ” A CORS POST solicitação funciona a partir de javascript simples, mas por que não com jQuery? “, Que observa que o jQuery 1.5.1 adiciona o

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

header para todos os pedidos de CORS. O jQuery 1.5.2 não faz isso. Além disso, de acordo com a mesma pergunta, definir um header de resposta do servidor

 Access-Control-Allow-Headers: * 

não permite que a resposta continue. Você precisa garantir que o header de resposta inclua especificamente os headers necessários. ie:

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

PEDIDO:

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

RESPOSTA:

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

Demorei algum tempo para encontrar a solução.

Caso sua resposta do servidor esteja correta e a solicitação seja o problema, você deve adicionar withCredentials: true aos xhrFields na solicitação:

 $.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 é obrigatório

Bem, eu lutei com essa questão por algumas semanas.

A maneira mais fácil, mais compatível e não hacky de fazer isso é provavelmente usar uma API JavaScript de provedor que não faça chamadas baseadas em navegador e possa manipular solicitações de Origem Cruzada.

Por exemplo, a API JavaScript do Facebook e a API do Google JS.

Caso seu provedor de API não esteja atualizado e não ofereça suporte ao header Cross Origin Resource Origin ‘*’ em sua resposta e não tenha uma API JS (Sim, estou falando sobre você, Yahoo), você é atingido por uma das três opções-

  1. Usando o jsonp em suas solicitações, que adiciona uma function de retorno de chamada ao seu URL, onde você pode manipular sua resposta. Advertência Isso alterará o URL de solicitação para que seu servidor de API seja equipado para manipular o? Callback = no final do URL.

  2. Envie a solicitação para o seu servidor de API, que é seu controlador e está no mesmo domínio que o cliente ou tem o compartilhamento de resources de origem cruzada habilitado, de onde é possível fazer proxy da solicitação para o servidor de API de terceiros.

  3. Provavelmente mais útil nos casos em que você está fazendo solicitações do OAuth e precisa lidar com a interação do usuário Haha! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')

Usar isso em combinação com o Laravel resolveu meu problema. Basta adicionar este header à sua solicitação de jquery Access-Control-Request-Headers: x-requested-with e certifique-se de que sua resposta do lado do servidor tenha este header definido como Access-Control-Allow-Headers: * .

Eu resolvi meu próprio problema ao usar a API de matriz de distância do google definindo meu header de solicitação com o jQuery ajax. Dê uma olhada abaixo.

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

Observe o que eu adicionei nas configurações
**

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

**
Eu espero que isso ajude.

Por alguma razão, uma questão sobre solicitações GET foi mesclada com essa, então vou responder aqui.

Esta function simples obterá de forma assíncrona uma resposta de status HTTP de uma página ativada por CORS. Se você executá-lo, verá que apenas uma página com os headers adequados retornará um status 200 se acessada via XMLHttpRequest – se GET ou POST for usado. Nada pode ser feito no lado do cliente para contornar isso, exceto possivelmente usando JSONP se você precisar apenas de um object json.

O seguinte pode ser facilmente modificado para obter os dados mantidos no 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

Eu tive exatamente o mesmo problema em que o jquery ajax só me dava problemas de cors em solicitações de postagens em que os pedidos funcionavam bem – cansei de tudo acima sem resultados. Eu tinha os headers corretos no meu servidor, etc Mudando para usar XMLHTTPRequest em vez de jquery corrigido meu problema imediatamente. Não importa qual versão do jquery eu usei, não consertei. A busca também funciona sem problemas, se você não precisar de compatibilidade com o navegador.

  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) 

Espero que isso ajude alguém com os mesmos problemas.

Este é um resumo do que funcionou para mim:

Defina uma nova function (envolvida $.ajax para simplificar):

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

Também trabalha com .done , .fail , etc:

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

Do lado do servidor (neste caso, onde example.com está hospedado), defina esses headers (incluímos alguns exemplos de código no 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); 

Esta é a única maneira que conheço para realmente fazer o cross-domain de JS.

O JSONP converte o POST em GET, que pode exibir informações confidenciais nos logs do servidor.

Isto é um pouco tarde para a festa, mas eu tenho lutado com isso por alguns dias. É possível e nenhuma das respostas que encontrei aqui funcionou. É enganosamente simples. Aqui está a chamada .ajax:

  < !DOCTYPE HTML>    Javascript Test