Bonnes pratiques d'utilisation des services Web de l'API Time Zone

Les services Web Google Maps Platform sont un ensemble d'interfaces HTTP envoyées à Google qui fournissent des données géographiques à vos applications cartographiques.

Ce guide décrit quelques pratiques courantes utiles pour configurer votre service Web requêtes et le traitement des réponses du service. Consultez le guide du développeur pour accéder à la documentation complète sur l'API Time Zone.

Qu'est-ce qu'un service Web ?

Les services Web Google Maps Platform sont une interface permettant de demander des données à l'API Google Maps services externes et l'utilisation des données dans vos applications Maps. Ces services sont conçu pour être utilisé avec une carte, conformément aux Restrictions liées aux licences dans les conditions d'utilisation de Google Maps Platform.

Les services Web des API Google Maps utilisent des requêtes HTTP(S) vers des URL spécifiques, en transmettant des paramètres d'URL et/ou Des données POST au format JSON en tant qu'arguments aux services. En général, ces services renvoient des données corps de la réponse au format JSON ou XML pour l'analyse et/ou traités par votre application.

Une requête type de l'API Time Zone est généralement du type ce formulaire:

https://maps.googleapis.com/maps/api/timezone/output?parameters

output indique le format de réponse (généralement json ou xml).

Remarque: Toutes les applications de l'API Time Zone nécessitent une authentification. En savoir plus sur les identifiants d'authentification

Accès SSL/TLS

HTTPS est requis pour toutes les requêtes Google Maps Platform qui utilisent des clés API ou contiennent un utilisateur données. Les requêtes effectuées via HTTP qui contiennent des données sensibles peuvent être rejetées.

Créer une URL valide

Vous pensez peut-être qu'une URL "valide" va de soi, mais ce n'est pas toujours le cas. Une URL saisie dans une barre d'adresse d'un navigateur, par exemple, peut contenir des caractères spéciaux (comme "上海+中國"). Le navigateur doit alors convertir en interne ces caractères en un autre code avant de les transmettre. De même, tout code qui génère ou accepte le format d'entrée UTF-8 peut considérer comme "valides" les URL contenant des caractères UTF-8, mais il doit convertir ces caractères avant de les envoyer à un serveur Web. Ce processus est appelé encodage d'URL ou encodage-pourcent.

Caractères spéciaux

Nous devons convertir les caractères spéciaux, car toutes les URL doivent respecter la syntaxe de la spécification Uniform Resource Identifier (URI). En fait, les URL doivent contenir un sous-ensemble spécifique de caractères ASCII (symboles alphanumériques courants), ainsi que des caractères réservés et utilisés comme caractères de commande dans les URL. Le tableau ci-dessous récapitule ces caractères :

Récapitulatif des caractères d'URL valides
Jeu decaractèresUtilisation de l'URL
Alphanumérique 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 Chaînes de texte, utilisation du schéma (http), port (8080), etc.
Non réservé - _ . ~ Chaînes de texte
Réservé ! * ' ( ) ; : @ & = + $ , / ? % # [ ] Caractères de commande et/ou chaînes de texte

Lorsque vous créez une URL valide, vous devez vous assurer qu'elle ne contient que les caractères figurant dans la section tableau. Vérifier qu'une URL utilise ce jeu de caractères permet généralement d'identifier deux problèmes (une omission et un remplacement) :

  • Les caractères que vous souhaitez utiliser ne figurent pas dans le tableau ci-dessus. Par exemple, les caractères de certaines langues étrangères (上海+中國, par exemple) doivent être encodés à l'aide des caractères ci-dessus. Selon une pratique courante, les espaces (qui ne sont pas autorisés dans les URL) sont également souvent représentés par le caractère '+'.
  • Des caractères figurent dans le tableau ci-dessus comme des caractères réservés, mais doivent être utilisés littéralement. Par exemple, ? est utilisé dans les URL pour indiquer le début de la chaîne de requête. Si vous souhaitez utiliser la chaîne "? et les Mysterions", vous devez encoder le caractère '?'.

Tous les caractères à encoder en URL le sont à l'aide du caractère '%' et d'une valeur hexadécimale à deux caractères correspondant à leur équivalent UTF-8. Par exemple, 上海+中國 au format UTF-8 serait encodé en URL sous la forme %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. La chaîne ? and the Mysterians serait encodée en URL sous la forme %3F+and+the+Mysterians ou %3F%20and%20the%20Mysterians.

Caractères courants qui doivent être encodés

Voici quelques caractères courants à encoder :

Caractère non fiable Valeur encodée
Espace %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

Convertir une URL envoyée par un utilisateur peut être difficile. Par exemple, un utilisateur peut saisir une adresse sous la forme "5&rue Longue". Généralement, vous devez créer votre URL à partir des éléments de cette adresse saisie, en traitant chaque entrée utilisateur comme des caractères littéraux.

En outre, les URL sont limitées à 16 384 caractères pour tous les services Web Google Maps Platform et les API Web statiques. Pour la plupart des services, ce nombre maximal de caractères est rarement atteint. Notez toutefois que certains services incluent plusieurs paramètres pouvant accroître la longueur des URL.

Bon usage des Google API

Les clients API mal conçus peuvent placer plus de charge que nécessaire à la fois sur Internet et vers les serveurs de Google. Cette section contient les bonnes pratiques pour les clients de ces API. Suivies ces bonnes pratiques peuvent vous aider à éviter que votre application soit bloquée pour cause d'abus involontaire de les API.

Intervalle exponentiel entre les tentatives

Dans de rares cas, un problème peut survenir lors du traitement de votre demande. il se peut que vous receviez un code code de réponse, ou la connexion TCP peut tout simplement échouer quelque part entre votre client et Google Cloud. Il est souvent utile de relancer la requête, la demande de suivi peut aboutir alors que la requête d'origine a échoué. Cependant, il est important de ne pas simplement des requêtes répétées aux serveurs Google. Ce comportement en boucle peut surcharger réseau entre votre client et Google, ce qui cause des problèmes pour de nombreuses parties.

Il est préférable de réessayer en allongeant progressivement les délais entre deux tentatives. En général, le retard est augmenté d'un facteur multiplicatif à chaque tentative, une approche connue sous le nom de Intervalle exponentiel entre les tentatives.

Prenons l'exemple d'une application qui souhaite envoyer cette requête à l'API Time Zone:

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

L'exemple Python suivant illustre comment effectuer la requête avec le retrait exponentiel :

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

Vous devez également veiller à ce qu'il n'y ait pas de code de nouvelle tentative plus haut dans l'appel de l'application qui entraîne des requêtes répétées rapidement.

Requêtes synchronisées

Un grand nombre de requêtes synchronisées vers les API Google peut ressembler à un réseau par déni de service (DDoS) sur l'infrastructure de Google, et traitées en conséquence. À vous devez vous assurer que les requêtes API ne sont pas synchronisées entre les clients.

Prenons l'exemple d'une application qui affiche l'heure dans le fuseau horaire actuel. Cette application définira probablement une alarme dans le système d'exploitation client qui l'activera à le début de la minute pour que l'heure affichée puisse être mise à jour. L'application doit pas d'appel d'API dans le cadre du traitement associé à cette alarme.

Effectuer des appels d'API en réponse à une alarme fixe n'est pas correct, car les appels d'API sont alors sont synchronisées en début de minute, même entre différents appareils, au lieu d'être répartis uniformément au fil du temps. Une application mal conçue qui procède ainsi produira un pic de de trafic à un niveau soixante fois normal au début de chaque minute.

Il est recommandé d'avoir une seconde alerte définie sur une heure choisie de manière aléatoire. Lorsque cette seconde alarme se déclenche, l'application appelle les API dont elle a besoin et stocke le résultats. Lorsque l'application souhaite mettre à jour l'affichage au début de la minute, elle utilise précédemment stockés au lieu d'appeler à nouveau l'API. Avec cette approche, les appels d'API sont réparties uniformément au fil du temps. De plus, les appels d'API ne retardent pas l'affichage lorsque l'écran en cours de mise à jour.

Soyez prudent avec d'autres heures de synchronisation courantes que le début de la minute. pas à cibler sont fixés au début d'une heure et le début de chaque journée à minuit.

Traitement des réponses

Cette section explique comment extraire ces valeurs de manière dynamique à partir des réponses d'un service Web.

Les services Web Google Maps fournissent des réponses faciles à comprendre, mais pas vraiment facile à utiliser. Lorsque vous exécutez une requête, que d'afficher un ensemble de données, vous souhaitez probablement extraire des données valeurs. En général, il est préférable d'analyser les réponses provenant du Web et extraire uniquement les valeurs qui vous intéressent.

Le schéma d'analyse que vous utilisez varie selon que vous renvoyez ou non au format XML ou JSON. des réponses JSON, étant déjà sous la forme Objets JavaScript, peuvent être traités dans JavaScript sur le client. Les réponses XML doivent être traitées à l'aide d'un processeur XML. et un langage de requête XML pour traiter les éléments au format XML. Nous utilisons XPath dans comme indiqué ci-dessous, car il est généralement compatible avec le traitement XML. bibliothèques.

Traitement XML avec XPath

XML est un format d'information structurée relativement mature, utilisé pour l'échange de données. Même s'il n'est pas aussi léger que JSON, XML propose davantage de langages et des outils plus robustes. Code pour le traitement XML en Java, par exemple, est intégré javax.xml packages.

Lors du traitement des réponses XML, vous devez utiliser langage de requête permettant de sélectionner les nœuds dans le document XML, que supposent que les éléments se trouvent à des positions absolues dans le Balisage XML. XPath est une syntaxe du langage pour décrire de manière unique les nœuds et les éléments dans un document XML. Les expressions XPath vous permettent d'identifier un contenu spécifique dans le document de réponse XML.

Expressions XPath

Une certaine connaissance de XPath permet de développer un schéma d'analyse robuste. Cette section se concentrera sur la façon dont les éléments dans un document XML sont traités avec XPath, ce qui vous permet traiter plusieurs éléments et construire des requêtes complexes.

XPath utilise des expressions pour sélectionner des éléments dans un fichier XML. document, en utilisant une syntaxe similaire à celle utilisée pour les chemins d'accès aux répertoires. Ces expressions identifient les éléments d'un document XML qui est une arborescence hiérarchique semblable à celle d'un DOM. En général, les expressions XPath sont gourmandes, indiquant ainsi qu'elles correspondra à tous les nœuds qui correspondent aux critères fournis.

Nous utiliserons l'extrait XML suivant pour illustrer exemples:

<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>

Sélection de nœud dans les expressions

Les sélections XPath sélectionnent des nœuds. Le nœud racine englobe l'ensemble du document. Vous sélectionnez ce nœud avec l'expression spéciale "/". Notez que la racine Le nœud n'est pas le nœud de premier niveau de votre document XML. en fait, se situe un niveau au-dessus de cet élément de premier niveau et inclut

Les nœuds d'éléments représentent les différents éléments du code XML arborescence de documents. Un élément <WebServiceResponse>, représente par exemple l'élément de niveau supérieur renvoyé dans notre dans l'exemple de service ci-dessus. Vous pouvez sélectionner des nœuds individuels chemins absolus ou relatifs, indiqués par la présence ou absence de "/" de début .

  • Chemin absolu : "/WebServiceResponse/result" sélectionne l'ensemble des <result> nœuds qui sont des enfants de <WebServiceResponse> ; d'un nœud. Notez que ces deux éléments sont issus de la racine le nœud "/".)
  • Chemin relatif à partir du contexte actuel: l'expression "result" correspond à n'importe quel <result> dans le contexte actuel. En général, vous ne devez pas vous n'avez pas à vous soucier du contexte, car vous traitez généralement des données via une expression unique.

L'une ou l'autre de ces expressions peut être enrichie par l'ajout d'un chemin d'accès générique, indiqué par une double barre oblique ("//"). Ce caractère générique indique qu'aucun ou plusieurs éléments peuvent correspondre dans le chemin intermédiaire. L'expression XPath "//formatted_address", par exemple, renverra tous les nœuds de ce nom dans le document actuel. L'expression //viewport//lat correspondrait à toutes Éléments <lat> pouvant tracer <viewport> en tant que parent.

Par défaut, les expressions XPath renvoient tous les éléments. Vous pouvez limiter pour que l'expression corresponde à un certain élément en fournissant un prédicat, placé entre crochets ([]). XPath l'expression "/GeocodeResponse/result[2] renvoie toujours deuxième résultat, par exemple.

Type d'expression
Nœud racine
Expression XPath : "/"
Sélection:
    <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>
    
Chemin absolu
Expression XPath : "/WebServiceResponse/result"
Sélection:
    <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>
    
Chemin avec générique
Expression XPath : "/WebServiceResponse//location"
Sélection:
    <location>
     <lat>37.4217550</lat>
     <lng>-122.0846330</lng>
    </location>
    
Chemin avec prédicat
Expression XPath : "/WebServiceResponse/result[2]/message"
Sélection:
    <message>The secret message</message>
    
Tous les enfants directs du premier result
Expression XPath : "/WebServiceResponse/result[1]/*"
Sélection:
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    
Le name d'un result dont le texte type est "sample."
Expression XPath : "/WebServiceResponse/result[type/text()='sample']/name"
Sélection:
    Sample XML
    

Il est important de noter que lorsque vous sélectionnez des éléments, vous sélectionnez des nœuds, pas seulement le texte qui se trouve dans ces objets. En général, vous va vouloir itérer sur tous les nœuds correspondants et extraire le texte. Toi peut également correspondre directement aux nœuds de texte ; voir Nœuds de texte ci-dessous.

Notez que XPath prend également en charge les nœuds d'attributs. Toutefois, tous les services Web Google Maps diffusent des éléments sans attribut. la correspondance des attributs n'est pas nécessaire.

Sélection de texte dans les expressions

Le texte d'un document XML est spécifié dans des expressions XPath via un opérateur de nœud de texte. Cet opérateur "text()" indique l'extraction de texte à partir du nœud indiqué. Par exemple : l'expression XPath "//formatted_address/text()" ; renvoyer tout le texte de <formatted_address> éléments.

Type d'expression
Tous les nœuds de texte (y compris les espaces vides)
Expression XPath : "//text()"
Sélection:
    sample
    Sample XML

    37.4217550
    -122.0846330
    The secret message
    
Sélection de texte
Expression XPath : "/WebServiceRequest/result[2]/message/text()"
Sélection:
    The secret message
    
Sélection en fonction du contexte
Expression XPath : "/WebServiceRequest/result[type/text() = 'sample']/name/text()"
Sélection:
    Sample XML
    

Vous pouvez également évaluer une expression et renvoyer un ensemble puis d'itérer sur cet "ensemble de nœuds", en extrayant de chaque nœud. Cette approche est utilisée dans l'exemple ci-dessous.

Pour en savoir plus sur XPath, consultez le Spécification XPath W3C

Évaluer XPath en Java

Java est compatible avec de nombreuses fonctionnalités d'analyse XML et d'utilisation d'expressions XPath. dans le package javax.xml.xpath.*. C'est pourquoi l'exemple de code présenté dans cette section utilise Java pour illustrer comment gérer XML et analyser les données des réponses du service XML ;

Pour utiliser XPath dans votre code Java, vous devez d'abord instancier une instance de XPathFactory et appeler newXPath() sur cette fabrique pour créer un objet XPath . Cet objet peut ensuite traiter les fichiers XML transmis et XPath à l'aide de la méthode evaluate().

Lors de l'évaluation d'expressions XPath, veillez à itérer sur tous les "ensembles de nœuds" possibles qui peut être renvoyée. Parce que ces sont renvoyés sous forme de nœuds DOM dans le code Java, vous devez capturer autant de valeurs dans un objet NodeList. itérer sur cet objet pour en extraire le texte ou les valeurs. nœuds.

Le code suivant montre comment créer un XPath attribuez-lui un fichier XML ainsi qu'une expression XPath, puis évaluez pour afficher le contenu pertinent.

import org.xml.sax.InputSource;
import org.w3c.dom.*;
import javax.xml.xpath.*;
import java.io.*;

public class SimpleParser {

  public static void main(String[] args) throws IOException {

	XPathFactory factory = XPathFactory.newInstance();

    XPath xpath = factory.newXPath();

    try {
      System.out.print("Web Service Parser 1.0\n");

      // In practice, you'd retrieve your XML via an HTTP request.
      // Here we simply access an existing file.
      File xmlFile = new File("XML_FILE");

      // The xpath evaluator requires the XML be in the format of an InputSource
	  InputSource inputXml = new InputSource(new FileInputStream(xmlFile));

      // Because the evaluator may return multiple entries, we specify that the expression
      // return a NODESET and place the result in a NodeList.
      NodeList nodes = (NodeList) xpath.evaluate("XPATH_EXPRESSION", inputXml, XPathConstants.NODESET);

      // We can then iterate over the NodeList and extract the content via getTextContent().
      // NOTE: this will only return text for element nodes at the returned context.
      for (int i = 0, n = nodes.getLength(); i < n; i++) {
        String nodeString = nodes.item(i).getTextContent();
        System.out.print(nodeString);
        System.out.print("\n");
      }
    } catch (XPathExpressionException ex) {
	  System.out.print("XPath Error");
    } catch (FileNotFoundException ex) {
      System.out.print("File Error");
    }
  }
}