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

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

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

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

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

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

В следующем примере показан REST GET запрос к методу list Map Configs :

https://mapmanagement.googleapis.com/v2beta/projects/PROJECT_NUMBER_OR_ID/mapConfigs

Включите токен OAuth в Authorization header вашего запроса.

Доступ по SSL/TLS

Для всех запросов к платформе Google Maps, использующих ключи API или содержащих пользовательские данные, требуется протокол HTTPS. Запросы, отправляемые по протоколу 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-адресах для обозначения начала строки запроса; если вы хотите использовать строку "? and the Mysterions", вам нужно закодировать символ '?' .

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