Ошибка Access-Control-Allow-Origin при отправке сообщения jQuery в API Google

143

Я много читал об ошибке «Access-Control-Allow-Origin», но не понимаю, что мне нужно исправить :(

Я играю с Google Moderator API, но когда пытаюсь добавить новую серию, получаю:

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.

Я пробовал с параметром обратного вызова и без него, пытался добавить в заголовок «Access-Control-Allow-Origin *». И я не знаю, как использовать здесь $ .getJSON, если применимо, потому что мне нужно добавить заголовок авторизации, и я не знаю, как это сделать без beforeCall из $ .ajax: /

Есть свет для этой тьмы уу?

Это код:

<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 -->
рубдоттоком
источник
1
не могли бы вы изложить свой код более полно? Я не смог запустить ваш код.
Хосейн Акаджани

Ответы:

251

Я решил ошибку Access-Control-Allow-Origin, изменив параметр dataType на dataType: 'jsonp' и добавив 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
});
рубдоттоком
источник
20
Я не думаю, что crossDomain:trueэто необходимо. Насколько я понимаю, это необходимо только в том случае, если вы делаете запрос в своем собственном домене, но хотите, чтобы jQuery обрабатывал его как междоменный запрос.
Alex W
7
crossDomainне нужен. это обычный jsonpзапрос, предназначенный для междоменного общения.
hitautodestruct 05
50
Я получаю такую ​​же ошибку, но хочу отправить запрос. jsonp не поддерживает POST. Как я могу это решить?
iamjustcoder
7
Вы также изменили свой метод с POST на GET
Дэйв Багданов,
5
@rubdottocom что, если url возвращает ответ xml вместо json ...?
Developer Desk,
43

У меня была точно такая же проблема, и это был не кросс-домен, а тот же домен. Я просто добавил эту строку в файл php, который обрабатывал запрос ajax.

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

Оно работало завораживающе. Благодаря плакату

Мухаммад Танвир
источник
29
Это очень небезопасно. Если кому-то удастся внедрить javascript на вашу страницу, он сможет легко «позвонить домой» с любой информацией, которую может предоставить пользователь.
dclowd9901 05
@ dclowd9901: «Небезопасно» является относительным, в зависимости от цели использования и мер, наблюдаемых для установки заголовка Access-Control-Allow-Origin как анонимный среди других причин.
nyedidikeke
6

Если эта ошибка возникает при попытке использовать службу, заголовок которой нельзя добавить Access-Control-Allow-Origin *в это приложение, но вы можете поставить перед сервером обратный прокси-сервер, ошибки можно избежать с помощью перезаписи заголовка.

Предполагая, что приложение работает на порту 8080 (общественное достояние на www.mydomain.com ), и вы помещаете обратный прокси на тот же хост на порт 80, это конфигурация обратного прокси 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 *;
    }   
}
Мариано Руис
источник
2
Как упоминалось выше, использование "*" очень небезопасно.
Adaddinsane
5
Да, но в зависимости от того, что вы раскрываете. Если вы публикуете публичный API без авторизации, это так (мой случай). Если нет, вам следует быть использованы somethig как это: Access-Control-Allow-Origin: http://example.com.
Мариано Руис
2
когда я тестирую api через почтальона и ajax. но запрос почтальона успешен. но в ajax верните false.
Araf
@Araf postman и другие приложения не активируют защиту CORS, встроенную в браузеры.
SenseiHitokiri
6

Да, в тот момент, когда jQuery видит, что URL-адрес принадлежит другому домену, он предполагает, что этот вызов является перекрестным, поэтому crossdomain:trueздесь не требуется.

Также важно отметить, что вы не можете выполнять синхронный вызов, $.ajaxесли ваш URL-адрес принадлежит другому домену (кросс-домен) или вы используете JSONP. Разрешены только асинхронные вызовы.

Примечание: вы можете вызвать сервис синхронно, если укажите в async:falseсвоем запросе.

Вивек Джайн
источник
1

попробуйте мой код на JavaScript

 var settings = {
              "url": "https://myinboxhub.co.in/example",
              "method": "GET",
              "timeout": 0,
              "headers": {},
            };
        $.ajax(settings).done(function (response) {
          console.log(response);
            if (response.auth) { 
                console.log('on success');
            } 
        }).fail(function (jqXHR, exception) { 
                var msg = '';
                if (jqXHR.status === '(failed)net::ERR_INTERNET_DISCONNECTED') {
                    
                        msg = 'Uncaught Error.\n' + jqXHR.responseText; 
                }
                if (jqXHR.status === 0) {
                        msg = 'Not connect.\n Verify Network.';
                } else if (jqXHR.status == 413) {
                        msg = 'Image size is too large.'; 
                }  else if (jqXHR.status == 404) {
                        msg = 'Requested page not found. [404]'; 
                } else if (jqXHR.status == 405) {
                        msg = 'Image size is too large.'; 
                } else if (jqXHR.status == 500) {
                        msg = 'Internal Server Error [500].'; 
                } else if (exception === 'parsererror') {
                        msg = 'Requested JSON parse failed.'; 
                } else if (exception === 'timeout') {
                        msg = 'Time out error.'; 
                } else if (exception === 'abort') {
                        msg = 'Ajax request aborted.'; 
                } else {
                        msg = 'Uncaught Error.\n' + jqXHR.responseText; 
                }
                console.log(msg);
        });;

В PHP

header('Content-type: application/json');
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET");
header("Access-Control-Allow-Methods: GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Content-Length, Accept-Encoding");
Йогендра Томар
источник
0

В моем случае проблему вызывает субдомен. Вот подробности

Я использовал app_development.something.com, здесь _поддомен подчеркивания ( ) создает ошибку CORS. После перехода app_developmentна app-developmentнего работает нормально.

Нуль
источник
0

Есть небольшой хак с php. И это работает не только с Google, но и с любым веб-сайтом, который вы не контролируете и не можете добавить Access-Control-Allow-Origin *.

Нам нужно создать PHP-файл (например, getContentFromUrl.php ) на нашем веб-сервере и сделать небольшой трюк.

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

Как это работает:

  1. Ваш браузер с помощью JS отправит запрос на ваш сервер
  2. Ваш сервер отправит запрос на любой другой сервер и получит ответ от другого сервера (любого веб-сайта)
  3. Ваш сервер отправит этот ответ на ваш JS

И мы можем делать события onClick, помещать это событие на какую-нибудь кнопку. Надеюсь, это поможет!

dfox
источник