Лучшие практики использования веб-служб Roads API

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

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

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

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

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

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

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

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

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

SSL/TLS-доступ

HTTPS требуется для всех запросов платформы Google Maps, которые используют ключи 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-адресом, кодируются с использованием символа '%' и двухсимвольного шестнадцатеричного значения, соответствующего их символу 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-адреса, полученного в результате пользовательского ввода, иногда бывает непростой задачей. Например, пользователь может ввести адрес «5-я и Мейн-стрит». Как правило, вам следует создавать URL-адрес из его частей, рассматривая любой ввод пользователя как буквальные символы.

Кроме того, длина URL-адресов всех веб-служб платформы Google Maps и статических веб-API ограничена 16 384 символами. Для большинства служб этот лимит символов достигается редко. Однако обратите внимание, что некоторые службы имеют несколько параметров, которые могут привести к созданию длинных 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 на клиенте.