Вы можете использовать службу Google API Discovery Service для создания различных инструментов для работы с API Google. Однако основная цель документа Discovery — предоставить Google возможность создавать клиентские библиотеки на различных языках программирования. В этом документе описывается, как создать собственную клиентскую библиотеку для API Google.
Стабильная и полнофункциональная клиентская библиотека — сложный инструмент, разработка которого может занять месяцы. Однако общие инструкции по созданию простой клиентской библиотеки для API Google можно свести к трем простым шагам:
- Извлечение документа Discovery и построение поверхности API
- Составление запроса
- Совершение вызова и получение ответа
Эти шаги более подробно описаны в следующих разделах. Вы также можете ознакомиться с примером клиента Simple APIs в разделе «Примеры», чтобы увидеть, как эти инструкции соотносятся с кодом.
Получить документ Discovery
Прежде чем приступить к реализации клиентской библиотеки, необходимо соблюсти ряд базовых требований, которые повлияют на ваш подход к разработке. Например, выбранный вами язык программирования может быть типизированным или нетипизированным; если он типизирован, он может быть как статически, так и динамически типизированным. Он может быть компилируемым или интерпретируемым. Эти требования будут определять ваш подход к использованию документа Discovery.
Первая задача разработки — извлечь документ Discovery. Ваша стратегия относительно того, когда именно этот документ будет извлечен, определяется сформулированными вами требованиями. Например, в статически типизированном языке вы можете извлечь документ Discovery на ранних этапах процесса, а затем сгенерировать код для работы с конкретным API, описанным в документе Discovery. Для строго типизированного языка вы можете сгенерировать код и собрать скомпилированную библиотеку. В динамически типизированном языке вы можете лениво конструировать программные структуры для взаимодействия с API «на лету» по мере использования программной поверхности.
Написать запрос
Составление запроса состоит из двух отдельных этапов:
- Составление тела запроса.
- Формирование URL-адреса запроса.
Вам необходимо преобразовать тело запроса (если таковое имеется) из представления, соответствующего языку, в корректный формат. Например, в клиентской библиотеке Java для каждого типа запроса может быть класс, позволяющий типобезопасную обработку данных запроса и сериализуемый в JSON.
Создание URL-адреса запроса — немного более сложный процесс.
Свойство path каждого метода в API использует синтаксис URI Template v04 . Это свойство может содержать переменные, заключенные в фигурные скобки. Вот пример свойства path с переменными:
/example/path/var
В приведённом выше пути var — это переменная. Значение этой переменной берётся из раздела parameters документа Discovery для данного метода. Каждому имени переменной соответствует значение в объекте parameters . В приведённом выше примере в разделе parameters есть параметр с именем var (и его свойство location — path , что указывает на то, что это переменная пути).
При создании запроса необходимо подставить значение var в URL. Например, если пользователь библиотеки сделает выбор, присвоив var значение foo , новый URL будет /example/path/foo .
Также обратите внимание, что свойство path представляет собой относительный URI. Чтобы вычислить абсолютный URI, выполните следующие действия:
- Если вы знаете своё местоположение (регион), и в документе Discovery есть свойство
endpoints, проверьте, присутствует ли ваше местоположение в спискеendpoints. Если да, выберитеendpointUrlиз спискаendpoints,locationкоторых совпадает с вашим. Если в документе Discovery нет свойства
endpointsили вашего местоположения нет в спискеendpoints, или вы хотите указать глобальную конечную точку, возьмите свойствоrootUrlиз верхнего уровня документа Discovery.Например, свойство
rootUrlв документе Discovery для API использования услуг имеет вид:https://serviceusage.googleapis.com/
- Возьмите
servicePathиз верхнего уровня документа Discovery. Например, свойствоservicePathв документе Discovery для API использования сервиса пустое. Объединим их вместе, чтобы получить:
https://serviceusage.googleapis.com/
Возьмите свойство
path, разверните его как шаблон URI и объедините результаты этого разворачивания с URI из предыдущего шага. Например, в методеserviceusage.services.enableAPI использования сервисов версии 1 значение свойстваpathравноv1/{+name}:enable. Таким образом, полный URI для метода выглядит следующим образом:https://serviceusage.googleapis.com/v1/{+name}:enable
Для вызова API использования сервиса ключ API не требуется. Однако, если вызываемый API требует ключ API, вы можете добавить его в строку запроса URI:
REQUEST_URI?key=API_KEY
Позвоните и получите ответ
После отправки запроса необходимо десериализовать ответ в соответствующее языковое представление, уделив внимание обработке возможных ошибок — как в базовом HTTP-транспорте, так и в сообщениях об ошибках, генерируемых службой API. Формат ошибок описан в руководстве Google по стилю JSON .
Примеры
В следующем разделе приведен простой пример клиентской библиотеки API.
Простой клиент API
Ниже приведён пример очень простой клиентской библиотеки, написанной на Python3. Клиент создаёт интерфейс для взаимодействия с API использования сервисов , а затем использует этот интерфейс для включения API Compute Engine ( compute.googleapis.com ) в проекте my-project .
import httplib2 import json import uritemplate import urllib # Step 1: Fetch Discovery document DISCOVERY_URI = "https://serviceusage.googleapis.com/$discovery/rest?version=v1" h = httplib2.Http() resp, content = h.request(DISCOVERY_URI) discovery = json.loads(content) location = None # Set this to your location if appropriate use_global_endpoint = True # Set this to False if you want to target the endpoint for your location # Step 2.a: Construct base URI BASE_URL = None if not use_global_endpoint and location: if discovery['endpoints']: BASE_URL = next((item['endpointUrl'] for item in discovery['endpoints'] if item['location'] == location), None) if not BASE_URL: BASE_URL = discovery['rootUrl'] BASE_URL += discovery['servicePath'] class Collection(object): pass def createNewMethod(name, method): # Step 2.b Compose request def newMethod(**kwargs): body = kwargs.pop('body', None) url = urllib.parse.urljoin(BASE_URL, uritemplate.expand(method['path'], kwargs)) for pname, pconfig in method.get('parameters', {}).items(): if pconfig['location'] == 'path' and pname in kwargs: del kwargs[pname] if kwargs: url = url + '?' + urllib.parse.urlencode(kwargs) return h.request(url, method=method['httpMethod'], body=body, headers={'content-type': 'application/json'}) return newMethod # Step 3.a: Build client surface def build(discovery, collection): for name, resource in discovery.get('resources', {}).items(): setattr(collection, name, build(resource, Collection())) for name, method in discovery.get('methods', {}).items(): setattr(collection, name, createNewMethod(name, method)) return collection # Step 3.b: Use the client service = build(discovery, Collection()) print (serviceusage.services.enable(name='projects/my-project/services/compute.googleapis.com'))
Важнейшими компонентами клиента являются:
- Шаг 1: Извлечение документа Discovery . Документ Discovery для API использования сервиса извлекается и преобразуется в структуру данных. Поскольку Python — язык с динамической типизацией, документ Discovery можно извлечь во время выполнения.
- Шаг 2.a: Построение базового URI . Базовый URI рассчитывается.
- Шаг 2.b: Составление запроса . При вызове метода для коллекции шаблон URI расширяется параметрами, переданными в метод, а параметры с указанием местоположения
queryдобавляются в параметры запроса URL. В заключение запрос отправляется на составленный URL с использованием HTTP-метода, указанного в документе Discovery. - Шаг 3.a: Создание клиентской поверхности . Клиентская поверхность строится путем рекурсивного нисходящего обхода разобранного документа Discovery. Для каждого метода в разделе
methodsк объектуCollectionприкрепляется новый метод. Поскольку коллекции могут быть вложенными, мы ищемresourcesи рекурсивно создаем объектCollectionдля всех его элементов, если таковой найден. Каждая вложенная коллекция также прикрепляется к объектуCollectionв качестве атрибута. - Шаг 3.b: Использование клиента . Это демонстрирует использование созданной поверхности API. Сначала создаётся объект службы на основе документа Discovery, затем API использования служб используется для включения API Compute Engine в проекте
my-project.