# Mejores Prácticas
# Importante
Los servicios web de la Plataforma Geodir son una colección de Interfaces HTTP para los servicios Geodir que brindan datos geográficos para sus aplicaciones de mapas. Esta guía describe técnicas para configurar solicitudes de servicios web y analizar las respuestas. Para obtener documentación específica de la API de Geofencing, consulte la Guía del Desarrollador (opens new window).
# ¿Qué es un Servicio Web?
Los servicios web de la Plataforma Geodir son una interfaz para solicitar datos de la API de Geofencing de servicios externos y utilizar los datos dentro de sus aplicaciones de Geofencing. Estos servicios están diseñados para ser utilizados junto con un mapa, según las restricciones de licencia en Geodir Términos de Servicio (opens new window).
Los servicios web de las API de Geofencing utilizan solicitudes HTTP a URL específicas y pasan parámetros de URL como argumentos a los servicios. Generalmente, estos servicios devuelven datos en la solicitud HTTP como JSON o XML para que su aplicación los analice o procese.
Una solicitud de servicio web típica de la API de Datacrime suele tener el siguiente formato:
https://apis.geodir.co/geofencing/v1/responseFormat?parameters
donde geofencing indica el servicio particular solicitado y la salida indica el formato de respuesta (generalmente json o xml).
Esta guía describe algunas prácticas comunes útiles para configurar sus solicitudes de servicios web y procesar sus respuestas de servicios web. Consulte la Guía del Desarrollador (opens new window), para obtener la documentación completa de la API de Geofencing.
Nota: Todas las aplicaciones de la API de Geofencing requieren autenticación. Obtenga más información sobre Credenciales de Autenticación (opens new window).
# Acceso SSL
https://apis.geodir.co/geofencing/v1/*outputFormat?parameters*
HTTPS es obligatorio para todas las solicitudes de servicio web de la API de Geofencing que contengan datos de usuario o identificadores de desarrollador. Las solicitudes realizadas a través de HTTP que incluyen datos confidenciales pueden rechazarse.
# URL Válida
Puede pensar que una URL "Válida" es evidente en blanco, pero ese no es el caso. Una URL ingresada dentro de una barra de direcciones en un navegador, por ejemplo, puede contener caracteres especiales (por ejemplo, "上海 + 中國"); el navegador necesita traducir internamente esos caracteres a una codificación diferente antes de la transmisión. Del mismo modo, cualquier código que genere o acepte la entrada UTF-8 podría tratar las URL 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 URL (opens new window).
Necesitamos traducir caracteres especiales porque todas las URL deben ajustarse a la sintaxis especificada por la especificación Identificador Uniforme de Recursos (URI) W3 (opens new window). En efecto, esto significa que las URL deben contener solo un subconjunto especial de caracteres ASCII: los símbolos alfanuméricos familiares y algunos caracteres reservados para usar como caracteres de control dentro de las URL. La siguiente tabla resume estos caracteres:
Conjunto | Caracteres | Uso de URL |
---|---|---|
Alphanumeric | 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 | Text strings, scheme usage (http), port (8080), etc. |
Unreserved | - _ . ~ | Text strings |
Reserved | ! * ' ( ) ; : @ & = + $ / ? % # [ ] | Control characters and/or Text Strings |
Al crear una URL válida, debe asegurarse de que contenga solo los caracteres que se muestran arriba. Conformar una URL para usar este conjunto de caracteres generalmente conduce a dos problemas, uno de omisión y otro de sustitución:
- Los caracteres que desea manejar existen fuera del conjunto anterior. Por ejemplo, los caracteres en idiomas extranjeros como 上海+中國 deben codificarse utilizando los caracteres anteriores. Por convención popular, los espacios (que no están permitidos dentro de las URL) a menudo también se representan con el carácter más '+'.
- Los caracteres existen dentro del conjunto anterior como caracteres reservados, pero deben usarse literalmente. Por ejemplo, ? se utiliza dentro de las URL para indicar el comienzo de la cadena de consulta; si desea utilizar la cadena "? Macchupicchu", deberá codificar el caracter '?'.
Todos los caracteres que se codificarán en URL se codifican con un carácter '%' y un valor hexadecimal de dos caracteres correspondiente a su carácter UTF-8. Por ejemplo, 上海+中國 en UTF-8 estaría codificado en URL como %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. La cadena ? Macchupicchu estaría codificado en URL como %3F+Macchupicchu.
Algunos caracteres comunes que deben codificarse son:
Caracter Inseguro | Valor Codificado |
---|---|
Space | %20 |
" | %22 |
+ | %2B |
, | %2C |
< | %3C |
> | %3E |
# | %23 |
% | %25 |
I | %7C |
Convertir una URL que recibe de la entrada del usuario a veces es complicado. Por ejemplo, un usuario puede ingresar una dirección como "Av Brasil&Bolivar". Generalmente, debe construir su URL a partir de sus partes, tratando cualquier entrada del usuario como caracteres literales.
Además, las URL están limitadas a 8000 caracteres para todos los servicios web. Para la mayoría de los servicios, rara vez se acercará a este límite de caracteres. Sin embargo, tenga en cuenta que ciertos servicios tienen varios parámetros que pueden resultar en URL largas.
# Uso adecuado de las APIs de Geodir
Los clientes de API mal diseñados pueden colocar más carga de la necesaria tanto en Internet como en los servidores de Geodir. Esta sección contiene algunas de las mejores prácticas para los clientes de las APIs. Seguir estas mejores prácticas puede ayudarlo a evitar que su aplicación sea bloqueada por abuso inadvertido de las APIs.
# Retroceso Exponencial
En casos excepcionales, algo puede salir mal al atender su solicitud; puede recibir un código de respuesta HTTP 4XX o 5XX, o la conexión TCP simplemente puede fallar en algún lugar entre su cliente y el servidor de Geodir. A menudo, vale la pena volver a intentar la solicitud, ya que la solicitud de seguimiento puede tener éxito cuando la original falló. Sin embargo, es importante no simplemente repetir las solicitudes a los servidores de Geodir. Este comportamiento de bucle puede sobrecargar la red entre su cliente y Geodir y causar problemas a muchas partes.
Un mejor enfoque es volver a intentarlo con retrasos crecientes entre intentos. Por lo general, la demora aumenta en un factor multiplicativo con cada intento, un enfoque conocido como Retroceso Exponencial (opens new window).
También debe tener cuidado de que no haya un código de reintento más alto en la cadena de llamadas de la aplicación que conduzca a solicitudes repetidas en rápida sucesión.
# Solicitudes Sincronizadas
Un gran número de solicitudes sincronizadas a las APIs de Geodir pueden parecer un ataque de Denegación de Servicio Distribuido (DDoS) en la infraestructura de Geodir y ser tratadas en consecuencia. Para evitar esto, debe asegurarse de que las solicitudes de API no estén sincronizadas entre clientes.
Por ejemplo, considere una aplicación que muestra la hora en la zona horaria actual. Esta aplicación probablemente establecerá una alarma en el sistema operativo del cliente y la activará al comienzo del minuto para que se pueda actualizar la hora mostrada. La aplicación no debe realizar ninguna llamada a la API como parte del procesamiento asociado con esa alarma.
Hacer llamadas a la API en respuesta a una alarma fija es malo, ya que las llamadas a la API se sincronizan al comienzo del minuto, incluso entre diferentes dispositivos, en lugar de distribuirse uniformemente a lo largo del tiempo. Una aplicación mal diseñada que haga esto producirá un pico de tráfico a sesenta veces los niveles normales al comienzo de cada minuto.
En cambio, un buen diseño posible es tener una segunda alarma configurada a una hora elegida al azar. Cuando se activa esta segunda alarma, la aplicación llama a las APIs que necesita y almacena los resultados. Cuando la aplicación desea actualizar su pantalla al comienzo del minuto, utiliza los resultados almacenados previamente en lugar de volver a llamar a la API. Con este enfoque, las llamadas a la API se distribuyen uniformemente a lo largo del tiempo. Además, las llamadas a la API no retrasan el procesamiento cuando se actualiza la pantalla.
Aparte del comienzo del minuto, otros tiempos de sincronización comunes que debe tener cuidado de no establecer son al comienzo de una hora y al comienzo de cada día a la medianoche.
# Procesando Respuestas
Los servicios web de Geodir proporcionan respuestas que son fáciles de entender, pero no exactamente fáciles de usar. Al realizar una consulta, en lugar de mostrar un conjunto de datos, probablemente desee extraer algunos valores específicos. Por lo general, querrá analizar las respuestas del servicio web y extraer solo los valores que le interesen.
El esquema de análisis que utiliza depende de si está devolviendo la salida en XML o JSON. Las respuestas JSON, que ya están en forma de objetos Javascript, pueden procesarse dentro de Javascript en blanco en el cliente; Las respuestas XML deben procesarse utilizando un procesador XML y un lenguaje de consulta XML para abordar los elementos dentro del formato XML. Usamos XPath en los siguientes ejemplos, ya que comúnmente se admite en bibliotecas de procesamiento XML.
# Procesando XML con XPath
XML es un formato de información estructurado relativamente maduro que se utiliza para el intercambio de datos. Aunque no es tan ligero como JSON, XML proporciona más soporte de lenguaje y herramientas más robustas. El código para procesar XML en Java, por ejemplo, está integrado en los paquetes javax.xml.
Al procesar respuestas XML, debe utilizar un lenguaje de consulta apropiado para seleccionar nodos dentro del documento XML, en lugar de asumir que los elementos residen en posiciones absolutas dentro del marcado XML. XPath es una sintaxis de lenguaje para describir de forma única nodos y elementos dentro de un documento XML. Las expresiones XPath le permiten identificar contenido específico dentro del documento de respuesta XML.
# Expresiones XPath
Cierta familiaridad con XPath contribuye en gran medida al desarrollo de un esquema de análisis sólido. Esta sección se centrará en cómo los elementos dentro de un documento XML se tratan con XPath, lo que le permite abordar varios elementos y construir consultas complejas.
XPath usa expresiones para seleccionar elementos dentro de un documento XML, usando una sintaxis similar a la que se usa para las rutas de directorio. Estas expresiones identifican elementos dentro de un árbol de documentos XML, que es un árbol jerárquico similar al de un DOM. Generalmente, las expresiones XPath son codiciosas, lo que indica que coincidirán con todos los nodos que coincidan con los criterios proporcionados.
Usaremos el siguiente XML abstracto para ilustrar nuestros ejemplos:
<WebServiceResponse>
<status>OK</status>
<result>
<type>sample</type>
<name>Sample XML</name>
<location>
<lat>37.4217550</lat>
<lng>-122.0846330</lng>
</location>
</result>
<result>
<message>The secret message</message>
</result>
</WebServiceResponse>
# Selección de Nodo en Expresiones
Las selecciones XPath seleccionan nodos. El nodo raíz abarca todo el documento. Seleccione este nodo utilizando la expresión especial "/". Tenga en cuenta que el nodo raíz no es el nodo de nivel superior de su documento XML; de hecho, reside un nivel por encima de este elemento de nivel superior y lo incluye.
Los nodos de elementos representan los diversos elementos dentro del árbol de documentos XML. Un elemento WebServiceResponse, por ejemplo, representa el elemento de nivel superior devuelto en nuestro servicio de muestra anterior. Puede seleccionar nodos individuales a través de rutas absolutas o relativas, indicadas por la presencia o ausencia de un carácter "/" inicial.
- Ruta absoluta: la expresión "/WebServiceResponse/result" selecciona todos los nodos de result que son hijos del nodo WebServiceResponse. (Tenga en cuenta que ambos elementos descienden del nodo raíz "/").
- Ruta relativa del contexto actual: la expresión "result" coincidiría con cualquier elemento de result dentro del contexto actual. En general, no debería tener que preocuparse por el contexto, ya que normalmente procesa los resultados del servicio web a través de una sola expresión.
Cualquiera de estas expresiones puede aumentarse mediante la adición de una ruta comodín, indicada con una barra doble ("//"). Este comodín indica que pueden coincidir cero o más elementos en la ruta intermedia. La expresión XPath "//name" por ejemplo, coincidirá con todos los nodos de ese nombre en el documento actual.
De forma predeterminada, las expresiones XPath coinciden con todos los elementos. Puede restringir la expresión para que coincida con un determinado elemento proporcionando un predicado, que se encierra entre corchetes ([]). La expresión XPath "/WebServiceResponse/result[2]" siempre devuelve el segundo resultado, por ejemplo.
Tipo de Expresión
Tipo | Descripción |
---|---|
Root node | XPath Expression: "/" Selection: |
Absolute Path | XPath Expression: "/WebServiceResponse/result" |
Selection: | |
Path with Wildcard | XPath Expression: "/WebServiceResponse//location" |
Selection: | |
Path with Predicate | XPath Expression: "/WebServiceResponse/result[2]/message" |
Selection: | |
All direct children of the first result | XPath Expression: "/WebServiceResponse/result[1]/*" |
Selection: | |
The name of a result whose type text is "sample." | XPath Expression: "/WebServiceResponse/result[type/text()='sample']/name" |
Selection: Sample XML|
Es importante tener en cuenta que al seleccionar elementos, selecciona nodos, no solo el texto dentro de esos objetos. Generalmente, querrá iterar sobre todos los nodos coincidentes y extraer el texto. También puede hacer coincidir los nodos de texto directamente.
# Selección de Texto en Expresiones
El texto dentro de un documento XML se especifica en expresiones XPath mediante un operador de nodo de texto. Este operador "text()" indica la extracción de texto del nodo indicado. Por ejemplo, la expresión XPath "//name/text()" devolverá todo el texto dentro de los elementos name.
Tipo de Expresión
Tipo | Descripción |
---|---|
All text nodes (including whitespace) | XPath Expression: "//text()" Selection: sample Sample XML 37.4217550 -122.0846330 The secret message |
Text Selection | XPath Expression: "/WebServiceRequest/result 2/message/text()" Selection: The secret message |
Context Sensitive Selection | XPath Expression: "/WebServiceRequest/result type/text() = 'sample'/name/text()" Selection: Sample XML |
Alternativamente, puede evaluar una expresión y devolver un conjunto de nodos y luego iterar sobre ese "conjunto de nodos", extrayendo el texto de cada nodo. Usamos este enfoque en el siguiente ejemplo.
Para obtener más información sobre XPath, consulte la Especificación XPath W3C (opens new window).
# Procesando JSON con JavaScript
JSON (Javascript Object Notation) tiene una ventaja obvia sobre XML en que la respuesta es liviana. Analizar este resultado es trivial en JavaScript, ya que el formato ya es un objeto válido de JavaScript. Por ejemplo, para extraer el valor de las claves 'standard_address' dentro de un objeto de resultado JSON, simplemente acceda a ellas usando el siguiente código:
for (i = 0; i < myJSONResult.results.length; i++) {
myAddress[i] = myJSONResult.results[i].standard_address;
}
Tenga en cuenta que debido a que JSON puede contener varios valores, es más prudente iterar sobre la longitud de la matriz de results si desea capturar todos los valores posibles. Sin embargo, en la práctica, es posible que desee devolver solo el primer resultado (results[0]).
Analizar JSON en otros idiomas es solo moderadamente más difícil. El siguiente ejemplo de Python inicia una solicitud de servicio web de Geofencing y muestra todos los valores standard_address resultantes al usuario dentro de una matriz:
import json
import urllib.request
### The maps_key defined below isn't a valid Geodir API Key.
### You need to obtain your own API Key.
### See https://docs.geodir.co/geocoding/obtain-your-api-key
API_KEY = "YOUR_API_KEY"
GEOCODE_BASE_URL = "https://apis.geodir.co/geofencing/v1/json"
def geocode(address):
# Join the parts of the URL together into one string.
params = urllib.parse.urlencode({"address": address, "key": API_KEY,})
url = f"{GEOCODE_BASE_URL}?{params}"
result = json.load(urllib.request.urlopen(url))
if result["status"] in ["OK", "ZERO_RESULTS"]:
return result["results"]
raise Exception(result["message"])
if __name__ == "__main__":
results = geocode(address="Av+Arequipa")
print(json.dumps([s["standard_address"] for s in results], indent=2))
Output:
[
"Lima, Lima, Lima, Perú"
]