Создайте клиентскую библиотеку

Вы можете использовать службу Google API Discovery Service для создания различных инструментов для работы с API Google. Однако основная цель документа Discovery — предоставить Google возможность создавать клиентские библиотеки на различных языках программирования. В этом документе описывается, как создать собственную клиентскую библиотеку для API Google.

Стабильная и полнофункциональная клиентская библиотека — сложный инструмент, разработка которого может занять месяцы. Однако общие инструкции по созданию простой клиентской библиотеки для API Google можно свести к трем простым шагам:

  1. Извлечение документа Discovery и построение поверхности API
  2. Составление запроса
  3. Совершение вызова и получение ответа

Эти шаги более подробно описаны в следующих разделах. Вы также можете ознакомиться с примером клиента Simple APIs в разделе «Примеры», чтобы увидеть, как эти инструкции соотносятся с кодом.

Получить документ Discovery

Прежде чем приступить к реализации клиентской библиотеки, необходимо соблюсти ряд базовых требований, которые повлияют на ваш подход к разработке. Например, выбранный вами язык программирования может быть типизированным или нетипизированным; если он типизирован, он может быть как статически, так и динамически типизированным. Он может быть компилируемым или интерпретируемым. Эти требования будут определять ваш подход к использованию документа Discovery.

Первая задача разработки — извлечь документ Discovery. Ваша стратегия относительно того, когда именно этот документ будет извлечен, определяется сформулированными вами требованиями. Например, в статически типизированном языке вы можете извлечь документ Discovery на ранних этапах процесса, а затем сгенерировать код для работы с конкретным API, описанным в документе Discovery. Для строго типизированного языка вы можете сгенерировать код и собрать скомпилированную библиотеку. В динамически типизированном языке вы можете лениво конструировать программные структуры для взаимодействия с API «на лету» по мере использования программной поверхности.

Написать запрос

Составление запроса состоит из двух отдельных этапов:

  1. Составление тела запроса.
  2. Формирование URL-адреса запроса.

Вам необходимо преобразовать тело запроса (если таковое имеется) из представления, соответствующего языку, в корректный формат. Например, в клиентской библиотеке Java для каждого типа запроса может быть класс, позволяющий типобезопасную обработку данных запроса и сериализуемый в JSON.

Создание URL-адреса запроса — немного более сложный процесс.

Свойство path каждого метода в API использует синтаксис URI Template v04 . Это свойство может содержать переменные, заключенные в фигурные скобки. Вот пример свойства path с переменными:

/example/path/var

В приведённом выше пути var — это переменная. Значение этой переменной берётся из раздела parameters документа Discovery для данного метода. Каждому имени переменной соответствует значение в объекте parameters . В приведённом выше примере в разделе parameters есть параметр с именем var (и его свойство locationpath , что указывает на то, что это переменная пути).

При создании запроса необходимо подставить значение var в URL. Например, если пользователь библиотеки сделает выбор, присвоив var значение foo , новый URL будет /example/path/foo .

Также обратите внимание, что свойство path представляет собой относительный URI. Чтобы вычислить абсолютный URI, выполните следующие действия:

  1. Если вы знаете своё местоположение (регион), и в документе Discovery есть свойство endpoints , проверьте, присутствует ли ваше местоположение в списке endpoints . Если да, выберите endpointUrl из списка endpoints , location которых совпадает с вашим.
  2. Если в документе Discovery нет свойства endpoints или вашего местоположения нет в списке endpoints , или вы хотите указать глобальную конечную точку, возьмите свойство rootUrl из верхнего уровня документа Discovery.

    Например, свойство rootUrl в документе Discovery для API использования услуг имеет вид:

    https://serviceusage.googleapis.com/
  3. Возьмите servicePath из верхнего уровня документа Discovery. Например, свойство servicePath в документе Discovery для API использования сервиса пустое.
  4. Объединим их вместе, чтобы получить:

    https://serviceusage.googleapis.com/
  5. Возьмите свойство path , разверните его как шаблон URI и объедините результаты этого разворачивания с URI из предыдущего шага. Например, в методе serviceusage.services.enable API использования сервисов версии 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 .