Erro de controle de acesso-permissão de origem ao enviar uma publicação do jQuery para as APIs do Google

143

Eu li muito sobre o erro 'Access-Control-Allow-Origin', mas não entendo o que tenho que corrigir :(

Estou brincando com a API do Google Moderator, mas quando tento adicionar uma nova série , recebo:

XMLHttpRequest cannot load 
https://www.googleapis.com/moderator/v1/series?key=[key]
&data%5Bdescription%5D=Share+and+rank+tips+for+eating+healthily+on+the+cheaps!
&data%5Bname%5D=Eating+Healthy+%26+Cheap
&data%5BvideoSubmissionAllowed%5D=false. 
Origin [my_domain] is not allowed by Access-Control-Allow-Origin.

Tentei com e sem o parâmetro de retorno de chamada, tentei adicionar 'Access-Control-Allow-Origin *' ao cabeçalho. E não sei como usar $ .getJSON aqui, se for o caso, porque tenho que adicionar o cabeçalho de autorização e não sei como fazê-lo sem beforeCall de $ .ajax: /

Alguma luz para esta escuridão uu?

Esse é o código:

<script src="http://www.google.com/jsapi"></script>

<script type="text/javascript">

var scope = "https://www.googleapis.com/auth/moderator";
var token = '';

function create(){
     if (token == '')
      token = doCheck();

     var myData = {
      "data": {
        "description": "Share and rank tips for eating healthily on the cheaps!", 
        "name": "Eating Healthy & Cheap", 
        "videoSubmissionAllowed": false
      }
    };

    $.ajax({

        url: 'https://www.googleapis.com/moderator/v1/series?key='+key,
        type: 'POST',
        callback: '?',
        data: myData,
        datatype: 'application/json',
        success: function() { alert("Success"); },
        error: function() { alert('Failed!'); },
        beforeSend: setHeader

    });
}

function setHeader(xhr) {

  xhr.setRequestHeader('Authorization', token);
}

function doLogin(){ 
    if (token == ''){
       token = google.accounts.user.login(scope);
    }else{
       alert('already logged');
    }
}


function doCheck(){             
    token = google.accounts.user.checkLogin(scope);
    return token;
}
</script>
...
...
<div data-role="content">
    <input type="button" value="Login" onclick="doLogin();">
    <input type="button" value="Get data" onclick="getModerator();">
    <input type="button" value="Create" onclick="create();">
</div><!-- /content -->
rubdottocom
fonte
1
você poderia colocar seu código um pouco mais completamente? Não consegui executar seu código.
Hosein Aqajani 16/10

Respostas:

249

Resolvi o erro Access-Control-Allow-Origin modificando o parâmetro dataType para dataType: 'jsonp' e adicionando um crossDomain: true

$.ajax({

    url: 'https://www.googleapis.com/moderator/v1/series?key='+key,
    data: myData,
    type: 'GET',
    crossDomain: true,
    dataType: 'jsonp',
    success: function() { alert("Success"); },
    error: function() { alert('Failed!'); },
    beforeSend: setHeader
});
rubdottocom
fonte
20
Eu não acho que isso crossDomain:trueé necessário. Pelo que entendi, isso só é necessário se você estiver fazendo uma solicitação em seu próprio domínio, mas quiser que o jQuery trate isso como uma solicitação entre domínios.
Alex W
7
crossDomainNão é necessário. essa é uma jsonpsolicitação regular que se destina à comunicação entre domínios.
precisa saber é o seguinte
50
Estou recebendo o mesmo erro, mas quero postar a solicitação. O jsonp não suporta POST. Como posso resolver isso?
Ianjustcoder
7
Você também mudou seu método de POST para GET
Dave Baghdanov
5
@rubdottocom what if url retorna resposta xml em vez de json ...?
Developer Desk
43

Eu tinha exatamente o mesmo problema e não era um domínio cruzado, mas o mesmo domínio. Acabei de adicionar esta linha ao arquivo php que estava manipulando a solicitação ajax.

<?php header('Access-Control-Allow-Origin: *'); ?>

Funcionou como um encanto. Graças ao pôster

Muhammad Tanweer
fonte
29
Isso é muito inseguro. Se alguém conseguir injetar javascript na sua página, poderá "telefonar para casa" facilmente com qualquer informação que um usuário possa fornecer.
precisa saber é o seguinte
@ dclowd9901: "Inseguro" é relativo, dependendo do objetivo do uso e das medidas observadas para definir o cabeçalho Access-Control-Allow-Origin como anônimo, entre outros motivos.
Neyedidikeke
6

Se você tiver esse erro ao tentar consumir um serviço que não pode adicionar o cabeçalho Access-Control-Allow-Origin *nesse aplicativo, mas poderá colocar na frente do servidor um proxy reverso, o erro poderá ser evitado com uma reescrita de cabeçalho.

Supondo que o aplicativo esteja sendo executado na porta 8080 (domínio público em www.mydomain.com ) e você coloque o proxy reverso no mesmo host na porta 80, esta é a configuração do proxy reverso do Nginx :

server {
    listen      80;
    server_name www.mydomain.com;
    access_log  /var/log/nginx/www.mydomain.com.access.log;
    error_log   /var/log/nginx/www.mydomain.com.error.log;

    location / {
        proxy_pass   http://127.0.0.1:8080;
        add_header   Access-Control-Allow-Origin *;
    }   
}
Mariano Ruiz
fonte
2
Como mencionado acima, usar '*' é muito inseguro.
Adaddinsane
5
Sim, mas dependendo do que você está expondo. Se você estiver publicando uma API pública sem autorização, é esse o caso (meu caso). Se não o fizer, deviam ser usado somethig assim: Access-Control-Allow-Origin: http://example.com.
Mariano Ruiz #
2
quando eu testar uma API através do carteiro e ajax. mas a solicitação do carteiro é um sucesso. mas no ajax retorne false.
Araf
O carteiro do @Araf e outros aplicativos não acionam as proteções do CORS incorporadas nos navegadores.
SenseiHitokiri
6

Sim, no momento em que o jQuery vê o URL pertencer a um domínio diferente, ele assume que a chamada é uma chamada entre domínios e, portanto, crossdomain:truenão é necessária aqui.

Além disso, é importante observar que você não pode fazer uma chamada síncrona $.ajaxse o URL pertencer a um domínio diferente (domínio cruzado) ou se estiver usando JSONP. Apenas chamadas assíncronas são permitidas.

Nota: você pode ligar para o serviço de forma síncrona se especificar async:falsecom sua solicitação.

Vivek Jain
fonte
0

No meu caso, o nome do subdomínio causa o problema. Aqui estão os detalhes

Eu usei app_development.something.com, aqui o _subdomínio underscore ( ) está criando um erro CORS. Depois de mudar app_developmentpara app-developmentele funciona bem.

Zero
fonte
0

Há um pequeno truque com php. E funciona não apenas com o Google, mas com qualquer site que você não controla e não pode adicionar Access-Control-Allow-Origin *

Precisamos criar um arquivo PHP (por exemplo, getContentFromUrl.php ) em nosso servidor da web e fazer um pequeno truque.

PHP

<?php

$ext_url = $_POST['ext_url'];

echo file_get_contents($ext_url);

?>

JS

$.ajax({
    method: 'POST',
    url: 'getContentFromUrl.php', // link to your PHP file
    data: {
        // url where our server will send request which can't be done by AJAX
        'ext_url': '/programming/6114436/access-control-allow-origin-error-sending-a-jquery-post-to-google-apis'
    },
    success: function(data) {
        // we can find any data on external url, cause we've got all page
        var $h1 = $(data).find('h1').html();

        $('h1').val($h1);
    },
    error:function() {
        console.log('Error');
    }
});

Como funciona:

  1. Seu navegador, com a ajuda de JS, enviará uma solicitação ao seu servidor
  2. Seu servidor enviará uma solicitação para qualquer outro servidor e obterá resposta de outro servidor (qualquer site)
  3. Seu servidor enviará esta resposta ao seu JS

E podemos fazer eventos em Click, colocar esse evento em algum botão. Espero que isso ajude!

dfox
fonte