Передовой опыт использования веб-сервисов Roads API

Оптимизируйте свои подборки Сохраняйте и классифицируйте контент в соответствии со своими настройками.

Веб-службы платформы Google Карт представляют собой набор HTTP-интерфейсов для служб Google, предоставляющих географические данные для ваших картографических приложений.

В этом руководстве описываются некоторые распространенные методы, полезные для настройки запросов веб-службы и обработки ответов службы. Полную документацию по Roads API см. в руководстве разработчика .

Что такое веб-сервис?

Веб-службы платформы Google Карт – это интерфейс для запроса данных API Карт из внешних служб и использования этих данных в ваших приложениях Карт. Эти сервисы предназначены для использования вместе с картой в соответствии с лицензионными ограничениями в Условиях обслуживания платформы Google Maps.

Веб-службы Maps API используют запросы HTTP(S) к определенным URL-адресам, передавая параметры URL и/или данные POST в формате JSON в качестве аргументов для служб. Как правило, эти службы возвращают данные в запросе HTTP(S) в виде JSON для синтаксического анализа и/или обработки вашим приложением.

Типичный запрос веб-службы Roads API обычно имеет следующую форму:

https://roads.googleapis.com/v1/snapToRoads?parameters&key=YOUR_API_KEY

где snapToRoads указывает конкретную запрошенную услугу. Другие службы дорог включают в себя nearestRoads и speedLimits .

Примечание . Все приложения Roads API требуют аутентификации. Получите дополнительную информацию об учетных данных для аутентификации .

SSL/TLS-доступ

HTTPS требуется для всех запросов платформы Google Карт, которые используют ключи API или содержат пользовательские данные. Запросы, сделанные по протоколу HTTP и содержащие конфиденциальные данные, могут быть отклонены.

Создание действительного URL-адреса

Вы можете подумать, что «действительный» URL-адрес самоочевиден, но это не совсем так. Например, URL-адрес, введенный в адресной строке браузера, может содержать специальные символы (например, "上海+中國" ); браузер должен внутренне перевести эти символы в другую кодировку перед передачей. Точно так же любой код, который генерирует или принимает ввод UTF-8, может рассматривать URL-адреса с символами UTF-8 как «действительные», но также должен переводить эти символы перед их отправкой на веб-сервер. Этот процесс называется URL-кодированием или процентным кодированием .

Специальные символы

Нам необходимо перевести специальные символы, поскольку все URL-адреса должны соответствовать синтаксису, указанному в спецификации универсального идентификатора ресурса (URI) . Фактически это означает, что URL-адреса должны содержать только специальное подмножество символов ASCII: знакомые буквенно-цифровые символы и некоторые зарезервированные символы для использования в качестве управляющих символов в URL-адресах. В этой таблице приведены эти символы:

Сводка допустимых символов URL
Установлен персонажи Использование URL
буквенно-цифровой abcdefghijklm nopqrstuvwxyz ABCDEFGHIJKLM NOPQRSTUVWXYZ 0 1 2 3 4 5 6 7 8 9 Текстовые строки, использование схемы ( http ), порт ( 8080 ) и т. д.
Незарезервировано - _ . ~ Текстовые строки
Сдержанный ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Управляющие символы и/или текстовые строки

При создании допустимого URL-адреса необходимо убедиться, что он содержит только те символы, которые указаны в таблице «Сводка допустимых символов URL-адреса». Согласование URL-адреса с использованием этого набора символов обычно приводит к двум проблемам: пропуску и замене:

  • Символы, с которыми вы хотите работать, существуют за пределами указанного выше набора. Например, символы иностранных языков, такие как上海+中國, необходимо кодировать с использованием указанных выше символов. По популярному соглашению, пробелы (которые не допускаются в URL-адресах) часто также представляются с помощью символа плюс '+' .
  • Символы существуют в указанном выше наборе как зарезервированные символы, но их необходимо использовать буквально. Например, ? используется в URL-адресах для указания начала строки запроса; если вы хотите использовать строку «? и Мистерионы», вам нужно будет закодировать '?' персонаж.

Все символы, которые должны быть закодированы в URL-адресе, кодируются с использованием символа '%' и двухсимвольного шестнадцатеричного значения, соответствующего их символу UTF-8. Например,上海+中國в UTF-8 будет кодироваться URL как %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B . Строка ? and the Mysterians будут закодированы в URL как %3F+and+the+Mysterians или %3F%20and%20the%20Mysterians .

Общие символы, которые нуждаются в кодировании

Некоторые общие символы, которые должны быть закодированы:

Небезопасный персонаж Закодированное значение
Пространство %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

Преобразование URL-адреса, который вы получаете от пользовательского ввода, иногда бывает сложной задачей. Например, пользователь может ввести адрес как «5th&Main St.» Как правило, вы должны создавать свой URL-адрес из его частей, рассматривая любой ввод пользователя как буквальные символы.

Кроме того, URL-адреса ограничены 8192 символами для всех веб-служб платформы Google Карт и статических веб-API. Для большинства служб это ограничение редко достигается. Однако обратите внимание, что у некоторых служб есть несколько параметров, которые могут привести к длинным URL-адресам.

Вежливое использование API Google

Плохо спроектированные клиенты API могут создавать большую нагрузку, чем необходимо, как для Интернета, так и для серверов Google. В этом разделе приведены некоторые рекомендации для клиентов API. Следование этим передовым методам может помочь вам избежать блокировки вашего приложения из-за непреднамеренного злоупотребления API.

Экспоненциальный откат

В редких случаях что-то может пойти не так при обслуживании вашего запроса; вы можете получить код ответа HTTP 4XX или 5XX, или соединение TCP может просто прерваться где-то между вашим клиентом и сервером Google. Часто имеет смысл повторить запрос, так как последующий запрос может быть выполнен успешно, если первоначальный потерпел неудачу. Однако важно не зацикливаться на повторных запросах к серверам Google. Такое зацикливание может привести к перегрузке сети между вашим клиентом и Google, что вызовет проблемы у многих сторон.

Лучшим подходом является повторная попытка с увеличением задержки между попытками. Обычно задержка увеличивается на мультипликативную величину с каждой попыткой, этот подход известен как экспоненциальная отсрочка .

Например, рассмотрим приложение, которое хочет сделать этот запрос к API часовых поясов:

https://maps.googleapis.com/maps/api/timezone/json?location=39.6034810,-119.6822510&timestamp=1331161200&key=YOUR_API_KEY

В следующем примере Python показано, как выполнить запрос с экспоненциальной задержкой:

import json
import time
import urllib.error
import urllib.parse
import urllib.request

# The maps_key defined below isn't a valid Google Maps API key.
# You need to get your own API key.
# See https://developers.google.com/maps/documentation/timezone/get-api-key
API_KEY = "YOUR_KEY_HERE"
TIMEZONE_BASE_URL = "https://maps.googleapis.com/maps/api/timezone/json"


def timezone(lat, lng, timestamp):

    # Join the parts of the URL together into one string.
    params = urllib.parse.urlencode(
        {"location": f"{lat},{lng}", "timestamp": timestamp, "key": API_KEY,}
    )
    url = f"{TIMEZONE_BASE_URL}?{params}"

    current_delay = 0.1  # Set the initial retry delay to 100ms.
    max_delay = 5  # Set the maximum retry delay to 5 seconds.

    while True:
        try:
            # Get the API response.
            response = urllib.request.urlopen(url)
        except urllib.error.URLError:
            pass  # Fall through to the retry loop.
        else:
            # If we didn't get an IOError then parse the result.
            result = json.load(response)

            if result["status"] == "OK":
                return result["timeZoneId"]
            elif result["status"] != "UNKNOWN_ERROR":
                # Many API errors cannot be fixed by a retry, e.g. INVALID_REQUEST or
                # ZERO_RESULTS. There is no point retrying these requests.
                raise Exception(result["error_message"])

        if current_delay > max_delay:
            raise Exception("Too many retry attempts.")

        print("Waiting", current_delay, "seconds before retrying.")

        time.sleep(current_delay)
        current_delay *= 2  # Increase the delay each time we retry.


if __name__ == "__main__":
    tz = timezone(39.6034810, -119.6822510, 1331161200)
    print(f"Timezone: {tz}")

Вы также должны быть осторожны, чтобы в цепочке вызовов приложения не было кода повторных попыток, который приводит к повторным запросам в быстрой последовательности.

Синхронизированные запросы

Большое количество синхронизированных запросов к API Google может выглядеть как атака распределенного отказа в обслуживании (DDoS) на инфраструктуру Google и рассматриваться соответствующим образом. Чтобы избежать этого, вы должны убедиться, что запросы API не синхронизируются между клиентами.

Например, рассмотрим приложение, которое отображает время в текущем часовом поясе. Это приложение, вероятно, установит будильник в клиентской операционной системе, чтобы разбудить его в начале минуты, чтобы отображаемое время можно было обновить. Приложение не должно выполнять никаких вызовов API в рамках обработки, связанной с этим сигналом тревоги.

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

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

Помимо начала минуты, другие распространенные моменты синхронизации, на которые следует обратить внимание, — это начало часа и начало каждого дня в полночь.

Обработка ответов

В этом разделе обсуждается, как динамически извлекать эти значения из ответов веб-службы.

Веб-сервисы Google Maps предоставляют ответы, которые легко понять, но не совсем удобно для пользователя. При выполнении запроса вместо отображения набора данных вы, вероятно, захотите извлечь несколько конкретных значений. Как правило, вам потребуется анализировать ответы веб-службы и извлекать только те значения, которые вас интересуют.

Используемая схема синтаксического анализа зависит от того, возвращаете ли вы выходные данные в формате JSON. Ответы JSON, уже представленные в виде объектов Javascript, могут обрабатываться внутри самого Javascript на клиенте.