Клиентский поиск картинок Google Contact

Я выбираю контакты Google в веб-приложении с помощью Google JavaScript API и хочу получить их фотографии.

Я делаю что-то вроде этого (сильно упрощено):

var token; // let's admit this is available already

function getPhotoUrl(entry, cb) {
  var link = entry.link.filter(function(link) {
    return link.type.indexOf("image") === 0;
  }).shift();
  if (!link)
    return cb(null);
  var request = new XMLHttpRequest();
  request.open("GET", link.href + "?v=3.0&access_token=" + token, true);
  request.responseType = "blob";
  request.onload = cb;
  request.send();
}

function onContactsLoad(responseText) {
  var data = JSON.parse(responseText);
  (data.feed.entry || []).forEach(function(entry) {
    getPhotoUrl(e, function(a, b, c) {
      console.log("pic", a, b, c);
    });
  });
}

Но я получаю эту ошибку как в Chrome, так и в Firefox:

Запрещен перекрестный запрос: та же политика происхождения запрещает чтение удаленного ресурса по адресу https://www.google.com/m8/feeds/photos/media/%3Cuser_email / ? V =3.0&access_token= , Это можно исправить, переместив ресурс в тот же домен или включив CORS.

Просматривая заголовки ответов с конечной точки каналов / фотографий, я вижу, что Access-Control-Allow-Origin: * не отправлено, следовательно, ошибка CORS я получаю.

Обратите внимание, что Access-Control-Allow-Origin: * отправляется при достижении feeds/contacts конечная точка, следовательно, разрешает междоменные запросы.

Это ошибка, или я что-то упустил из их документов?

2 ответа

Пока не могу комментировать, поэтому этот ответ...

Очевидно, вы уже настроили правильный идентификатор клиента и происхождение JavaScript в консоли разработчиков Google.

Похоже, что API общих контактов домена не работает так, как рекламируется, и выполняет только обещание CORS, когда вы запрашиваете JSONP данные (ваш код указывает, что вы получили свои входные данные, используя JSON). Для формата JSON API устанавливает access-control-allow-origin * вместо источников JavaScript, перечисленных вами для вашего проекта.

Но по состоянию на сегодня (2015-06-16), если вы попытаетесь выдать GET, POST... с другим типом данных (например, atom/xml), Google API вообще не будет устанавливать access-control-allow-origin, поэтому ваш браузер отклонит ваш запрос на доступ к данным (ошибка 405).

Это явно ошибка, которая препятствует любому программному использованию API общих контактов, но для простого перечисления записей: больше нельзя создавать, обновлять, удалять записи или получать доступ к фотографиям.

Пожалуйста, поправьте меня, если я ошибаюсь (я хочу, чтобы я был); пожалуйста, прокомментируйте или отредактируйте, если вы знаете лучший способ отправить эту ошибку в Google.

Обратите внимание, для полноты картины приведен скелет кода, который я использую для доступа к контактам (требуется jQuery).

    <button id="authorize-button" style="visibility: hidden">Authorize</button>
    <script type="text/javascript">
        var clientId = 'TAKE-THIS-FROM-CONSOLE.apps.googleusercontent.com',
            apiKey = 'TAKE-THAT-FROM-GOOGLE-DEVELOPPERS-CONSOLE',
            scopes = 'https://www.google.com/m8/feeds';
        // Use a button to handle authentication the first time.
        function handleClientLoad () {
            gapi.client.setApiKey ( apiKey );
            window.setTimeout ( checkAuth, 1 );
        }
        function checkAuth() {
            gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
        }
        function handleAuthResult ( authResult ) {
            var authorizeButton = document.getElementById ( 'authorize-button' );
            if ( authResult && !authResult.error ) {
                authorizeButton.style.visibility = 'hidden';
                var cif = {
                    method: 'GET',
                    url:  'https://www.google.com/m8/feeds/contacts/mydomain.com/full/',
                    data: {
                        "access_token": authResult.access_token,
                        "alt":          "json",
                        "max-results":  "10"
                    },
                    headers: { 
                        "Gdata-Version":    "3.0"    
                    },
                    xhrFields: {
                        withCredentials: true
                    },
                    dataType: "jsonp"
                };
                $.ajax ( cif ).done ( function ( result ) {
                        $ ( '#gcontacts' ).html ( JSON.stringify ( result, null, 3 ) );
                } );
            } else {
                authorizeButton.style.visibility = '';
                authorizeButton.onclick = handleAuthClick;
            }
        }
        function handleAuthClick ( event ) {
            gapi.auth.authorize ( { client_id: clientId, scope: scopes, immediate: false }, handleAuthResult );
            return false;
        }
    </script>
    <script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
    <pre id="gcontacts"></pre>

Если вы замените cif.data.alt от atom и / или cif.dataType от xml, вы получите печально известную ошибку 405.

ps: cif, конечно, связан с ajax;-)

Предполагая, что вам нужна только "картинка профиля", попробуйте переместить запрос этого изображения непосредственно в HTML, указав полный URL-адрес в качестве src элемент <img> тег (с ?access_token=<youknowit> в конце).

Например, используя Angular.js

<img ng-src="{{contact.link[1].href + tokenForImages}}" alt="photo" />

Что касается CORS в целом, кажется, что существует довольно много мест, где доступ к API из JS не работает должным образом.

Надеюсь это поможет.

Другие вопросы по тегам