Prácticas recomendadas para usar los servicios web de la API de Pollen

Los servicios web de Google Maps Platform son un conjunto de interfaces HTTP para los servicios de Google que proporcionan datos geográficos para tus aplicaciones de mapas.

En esta guía, se describen algunas prácticas comunes que resultan útiles para configurar tus solicitudes de servicios web y procesar las respuestas de los servicios. Consulta la guía para desarrolladores para obtener la documentación completa de la API de Pollen.

¿Qué es un servicio web?

Los servicios web de Google Maps Platform son una interfaz para solicitar datos de la API de Google Maps a servicios externos y utilizar esos datos en tus aplicaciones de Maps. Estos servicios están diseñados para usarse junto con un mapa, de acuerdo con las Restricciones de licencia de las Condiciones del Servicio de Google Maps Platform.

Los servicios web de las APIs de Maps usan solicitudes HTTP(S) a URLs específicas y les pasan a los servicios parámetros de URLs o datos POST en formato JSON como argumentos. Por lo general, estos servicios muestran datos en el cuerpo de la respuesta como JSON para que la aplicación los analice o los procese.

En el siguiente ejemplo, se muestra la URL de una solicitud GET de REST al método forecast:lookup:

https://pollen.googleapis.com/v1/forecast:lookup?&key=API_KEY

Nota: Todas las aplicaciones de la API de Pollen requieren autenticación. Obtén más información sobre las credenciales de autenticación.

Acceso SSL/TLS

Se requiere HTTPS para todas las solicitudes de Google Maps Platform que usan claves de API o contienen datos del usuario. Es posible que se rechacen las solicitudes realizadas a través de HTTP que contengan datos sensibles.

Cómo crear una URL válida

Tal vez creas que una dirección URL "válida" es evidente, pero no siempre es así. Una URL que se ingresa en una barra de direcciones en un navegador, por ejemplo, puede contener caracteres especiales (p. ej., "上海+中國"), y el navegador debe traducir internamente esos caracteres a una codificación diferente antes de la transmisión. Con el mismo token, cualquier código que genere o acepte entradas en UTF-8 podría procesar las URLs con caracteres UTF-8 como "válidas", pero también necesitaría traducir esos caracteres antes de enviarlos a un servidor web. Este proceso se llama codificación de URLs o codificación por ciento.

Caracteres especiales

Debemos traducir los caracteres especiales porque todas las URLs deben cumplir con los requisitos de sintaxis que se indican en la especificación Identificador de recursos uniformes (URI). En efecto, esto significa que las URLs deben contener solo un subconjunto especial de caracteres ASCII: los símbolos alfanuméricos que ya conocemos y algunos caracteres reservados para usar como caracteres de control en las URLs, los cuales se resumen en la siguiente tabla:

Resumen de caracteres válidos para URLs
ConjuntocaracteresUso en la URL
Alfanuméricos a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 Cadenas de texto, uso de esquemas (http), puerto (8080), etcétera
No reservados - _ . ~ Cadenas de texto
Reservados ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Caracteres de control o cadenas de texto

Cuando crees una URL válida, debes asegurarte de que contenga solo los caracteres que se muestran en la tabla. Adaptar una dirección URL para usar este conjunto de caracteres generalmente provoca dos problemas, de omisión y de sustitución:

  • Quizá quieras usar caracteres que no se encuentran dentro del conjunto anterior. Por ejemplo, los caracteres de otros idiomas, como 上海+中國, deben codificarse con los caracteres que se indican arriba. Por convención popular, los espacios (que no se permiten en las URLs) suelen representarse también con el carácter de signo más '+'.
  • Hay caracteres dentro del conjunto anterior que son caracteres reservados, pero se deben usar literalmente. Por ejemplo, ? se usa en las URLs para indicar el comienzo de la cadena de consulta; si deseas utilizar la cadena "? and the Mysterions", debes codificar el carácter '?'.

La codificación de caracteres para URLs usa un carácter '%' y un valor hexadecimal de dos caracteres correspondiente a su carácter en UTF-8. Por ejemplo, 上海+中國 en UTF-8 se codificaría como %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B para usarse en URLs. La cadena ? and the Mysterians se codificaría como %3F+and+the+Mysterians o %3F%20and%20the%20Mysterians para usarse en URLs.

Caracteres comunes que necesitan codificación

A continuación se indican algunos de los caracteres que se deben codificar:

Caracteres no seguros Valor codificado
Espacio %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

Convertir una dirección URL que recibes a través de la entrada de un usuario puede ser engañoso. Por ejemplo, un usuario puede ingresar la dirección "5th&Main St.". Generalmente, deberías crear tu URL a partir de sus partes y tratar las entradas del usuario como caracteres literales.

Además, las URLs tienen una limitación de 16,384 caracteres en todos los servicios web y las APIs web estáticas de Google Maps Platform. Para la mayoría de los servicios, este límite de caracteres rara vez se alcanza. No obstante, ten en cuenta que algunos servicios tienen varios parámetros que podrían generar URLs extensas.

Uso normal de las API de Google

Los clientes de API de diseño deficiente pueden presentar una mayor carga que la necesaria en Internet y en los servidores de Google. En esta sección se explican algunas de las prácticas recomendadas para los clientes de las API. Seguir estas prácticas recomendadas puede ayudarte a evitar que tu aplicación se bloquee debido a abusos accidentales de las APIs.

Interrupción exponencial

En casos excepcionales, puede producirse un error en la entrega de tu solicitud; es posible que recibas un código de respuesta HTTP 4XX o 5XX, o que la conexión TCP simplemente falle en algún punto entre tu cliente y el servidor de Google. A menudo, vale la pena volver a intentar realizar la solicitud debido a que, cuando falle la primera la solicitud, la siguiente puede ser exitosa. Sin embargo, es importante no realizar varias solicitudes repetidas a los servidores de Google. Este comportamiento repetitivo puede sobrecargar la red entre tu cliente y Google, y causar problemas para varias partes.

Un mejor enfoque consiste en realizar nuevos intentos con demoras más prolongadas entre uno y otro. Por lo general, la demora aumenta conforme a un factor multiplicativo con cada intento; un enfoque conocido como retirada exponencial.

Por ejemplo, considera una aplicación que desee realizar esta solicitud a la API de Time Zone:

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

En el siguiente ejemplo de Python se muestra la manera de realizar la solicitud con interrupción exponencial:

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}")

También debes tener la precaución de que no haya un código de reintento más alto en la cadena de llamada de la aplicación que provoque solicitudes repetidas en una sucesión rápida.

Solicitudes sincronizadas

Una gran cantidad de solicitudes sincronizadas a las API de Google puede parecer un ataque de denegación de servicio distribuido (DDoS) en la infraestructura de Google y debe tratarse según corresponda. Para evitar esto, debes asegurarte de que las solicitudes de API no se sincronicen entre clientes.

Por ejemplo, considera una aplicación que muestre la hora en la zona horaria actual. Es probable que esta aplicación configure una alarma en el sistema operativo del cliente que lo despierte al inicio del minuto, de modo que la hora que se muestra pueda actualizarse. La aplicación no debe realizar llamadas a la API como parte del procesamiento asociado con esa alarma.

Realizar llamadas a la API en respuesta a una alarma fija no es recomendable, ya que provoca que las llamadas a la API se sincronicen al inicio del minuto, incluso entre diferentes dispositivos, en lugar de distribuirse de forma pareja con el tiempo. Una aplicación mal diseñada que hace esto producirá un aumento repentino de tráfico al inicio de cada minuto que equivale a sesenta veces los niveles normales.

En su lugar, un posible buen diseño es tener una segunda alarma configurada en una hora elegida al azar. Cuando esta segunda alarma se activa, la aplicación llama a las APIs que necesita y almacena los resultados. Cuando la aplicación quiere actualizar su pantalla al comienzo del minuto, usa los resultados almacenados con anterioridad en lugar de volver a llamar a la API. Con este enfoque, las llamadas a la API se distribuyen de forma equitativa con el tiempo. Además, las llamadas a la API no retrasan la renderización cuando se actualiza la pantalla.

Además de la sincronización al inicio del minuto, con otros momentos de sincronización comunes se debe tener la precaución de que no se produzcan al inicio de la hora y al inicio de cada día a la medianoche.

Procesamiento de respuestas

En esta sección se discute cómo extraer esos valores de forma dinámica de las respuestas de los servicios web.

Los servicios web de Google Maps proporcionan respuestas fáciles de comprender, pero que no son exactamente prácticas para el usuario. Cuando realizas una consulta, en lugar de mostrar un conjunto de datos, te recomendamos que extraigas algunos valores específicos. En general, se recomienda que analices las respuestas del servicio web y extraigas solo los valores que te interesen.

El esquema de análisis que uses depende de si muestras el resultado en JSON. Las respuestas JSON, que ya tienen forma de objetos de JavaScript, se pueden procesar dentro de JavaScript en el cliente.