4

Я собираю контакты google в webapp с помощью API JavaScript JavaScript, и я хотел бы получить их фотографии.Клиентский поиск изображений контактов Google

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

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:

Cross-Origin Request блокированного: The Same Политика происхождения запрещает чтение удаленного ресурса по адресу https://www.google.com/m8/feeds/photos/media/<user_email>/< some_contact_id>? V = 3.0 & access_token = < obfuscated>. Это можно устранить, переместив ресурс в тот же домен или включив CORS.

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

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

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

ответ

1

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

E.g. используя Angular.js

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

Что касается CORS в целом, кажется, есть довольно много мест, где доступ к API-интерфейс от JS не работает, как ожидалось.

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

2

не в состоянии комментировать пока, следовательно, этот ответ ...

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

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

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

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

Пожалуйста, исправьте меня, если я ошибаюсь (я бы хотел); прокомментируйте или отредактируйте, если вы знаете, как наилучшим образом подать эту ошибку в 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.

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

Смежные вопросы