Best practice per l'utilizzo dei servizi web dell'API Time Zone

I servizi web di Google Maps Platform sono una raccolta di interfacce HTTP di Google che forniscono dati geografici per le applicazioni di Google Maps.

Questa guida descrive alcune pratiche comuni utili per configurare il tuo servizio web ed elaborare le risposte dei servizi. Consulta la guida per gli sviluppatori. per la documentazione completa dell'API Time Zone.

Che cos'è un servizio web?

I servizi web di Google Maps Platform sono un'interfaccia per richiedere i dati dell'API di Google Maps da da servizi esterni e utilizzare i dati all'interno delle applicazioni Maps. Questi servizi progettata per essere utilizzata insieme a una mappa, come Limitazioni di licenza nei Termini di servizio di Google Maps Platform.

I servizi web delle API di Google Maps utilizzano richieste HTTP(S) a URL specifici, trasmettendo parametri URL e/o Dati POST in formato JSON come argomenti per i servizi. In genere, questi servizi restituiscono i dati corpo della risposta in formato JSON o XML per l'analisi e/o all'elaborazione da parte dell'utente.

Una tipica richiesta API Time Zone è in genere del modulo seguente:

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

dove output indica il formato della risposta (di solito json o xml).

Nota: tutte le applicazioni API Time Zone richiedono l'autenticazione. Leggi ulteriori informazioni sulle credenziali di autenticazione.

Accesso SSL/TLS

HTTPS è richiesto per tutte le richieste di Google Maps Platform che utilizzano chiavi API o che contengono e i dati di Google Cloud. Le richieste effettuate tramite HTTP che contengono dati sensibili potrebbero essere rifiutate.

Creazione di un URL valido

Potresti pensare che uno stato "valido" l'URL è chiaro, ma non è esattamente così. Un URL inserito in una barra degli indirizzi in un browser, ad esempio, può contenere caratteri speciali (come "上海+中國"); il browser deve tradurre internamente quei caratteri in una codifica diversa prima della trasmissione. Per lo stesso token, qualsiasi codice che generi o accetta input UTF-8 potrebbe considerare "validi" gli URL con caratteri UTF-8, ma richiederebbe anche per tradurre quei caratteri prima di inviarli a un server web. Questa procedura è denominata Codifica degli URL o codifica percentuale.

Caratteri speciali

Dobbiamo tradurre i caratteri speciali tutti gli URL devono essere conformi alla sintassi specificata dal Uniforme URI (Resource Identifier). In effetti, ciò significa che gli URL deve contenere solo un sottoinsieme speciale di caratteri ASCII: il simboli alfanumerici e alcuni caratteri riservati da utilizzare come controllo all'interno degli URL. Questa tabella riassume questi caratteri:

Riepilogo dei caratteri di URL validi
ConfiguracaratteriUtilizzo dell'URL
Alfanumerico 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 Stringhe di testo, utilizzo dello schema (http), porta (8080) e così via.
Non prenotato - _ ~ Stringhe di testo
Prenotato ! * ' ( ) : @ e = + $ , / ? % # [ ] Caratteri di controllo e/o stringhe di testo

Quando crei un URL valido, devi assicurarti che contenga solo i caratteri mostrati nei campi . Conformità di un URL all'utilizzo generale di questo insieme di caratteri causa due problemi, uno di omissione e uno di sostituzione:

  • I caratteri che vuoi gestire esistono al di fuori sopra l'insieme. Ad esempio, caratteri in lingue straniere come 上海+中國, devono essere codificati utilizzando sopra i caratteri. Per convenzione popolare, gli spazi (che sono non consentite negli URL) sono spesso rappresentate con il '+' carattere.
  • I caratteri all'interno di questo intervallo sono impostati come riservati, ma che devono essere usati letteralmente. Ad esempio, ? viene utilizzato negli URL per indicare l'inizio della stringa di query; se vuoi utilizzare stringa "? and the Mysterions" dovresti codificare il modello '?' carattere.

Tutti i caratteri da codificare nell'URL sono codificati utilizzando un carattere '%' e un esadecimale a due caratteri corrispondente al carattere UTF-8. Ad esempio: 上海+中國 in UTF-8 verrebbe codificato come URL %E4%B8%8A%E6%B5%B7%2B%E4%B8%AD%E5%9C%8B. La la stringa ? and the Mysterians verrebbe codificata come URL %3F+and+the+Mysterians o %3F%20and%20the%20Mysterians.

Caratteri comuni che richiedono la codifica

Alcuni caratteri comuni che devono essere codificati sono:

Carattere non sicuro Valore codificato
Spazio %20
" %22
< %3C
> %3E
# %23
% %25
| %7C

A volte la conversione di un URL ricevuto dall'input dell'utente può essere difficile. Ad esempio, un utente potrebbe inserire l'indirizzo "Via Roma 12". In genere, devi generare l'URL partendo dalle sue parti, tenendo presente che qualsiasi input utente come caratteri letterali.

Inoltre, gli URL sono limitati a 16.384 caratteri per tutti i servizi web di Google Maps Platform e le API web statiche. Per la maggior parte dei servizi, questo limite di caratteri viene raramente raggiunto. Tuttavia, tieni presente che alcuni servizi hanno diversi parametri che possono generare URL lunghi.

Utilizzo discreto delle API di Google

I client API progettati in modo scorretto possono applicare più carico del necessario sia su Internet sia nei server di Google. Questa sezione contiene alcune best practice per i client delle API. Persone che seguo queste best practice possono aiutarti a evitare che la tua applicazione venga bloccata per comportamenti illeciti involontari le API.

Backoff esponenziale

In rari casi, si potrebbe verificare un problema nella gestione della tua richiesta. potresti ricevere un HTTP 4XX o 5XX del codice di risposta o semplicemente la connessione TCP non riesce in qualche punto tra il client o server web. Spesso vale la pena ritentare la richiesta la richiesta di follow-up potrebbe avere esito positivo se l'originale non è andato a buon fine. Tuttavia, è importante non limitarsi a effettuare ripetutamente richieste ai server di Google. Questo comportamento di loop può sovraccaricare tra il tuo client e Google, causando problemi a molte parti.

Un approccio migliore è riprovare con un ritardo maggiore tra un tentativo e l'altro. Di solito il ritardo viene aumentato di un fattore moltiplicativo a ogni tentativo, un approccio noto Backoff esponenziale.

Ad esempio, consideriamo un'applicazione che vuole effettuare questa richiesta l'API Time Zone:

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

Il seguente esempio Python mostra come effettuare la richiesta con backoff esponenziale:

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

Devi inoltre fare attenzione che la chiamata all'applicazione non includa un nuovo codice per un nuovo tentativo che porta a richieste ripetute in rapida successione.

Richieste sincronizzate

Un numero elevato di richieste sincronizzate alle API di Google può apparire come Attacco DoS (Denial of Service) all'infrastruttura di Google e da trattare di conseguenza. A evita questo, devi assicurarti che le richieste API non siano sincronizzate tra i clienti.

Ad esempio, considera un'applicazione che mostra l'ora nel fuso orario attuale. Questa applicazione probabilmente imposterà un allarme nel sistema operativo client per riattivarlo alle l'inizio del minuto in modo che l'ora visualizzata possa essere aggiornata. L'applicazione dovrebbe non effettuare chiamate API nell'ambito dell'elaborazione associata a questo allarme.

Effettuare chiamate API in risposta a un allarme fisso è un'azione negativa perché le chiamate API vengono sincronizzati all'inizio, anche tra dispositivi diversi, invece di essere distribuiti in modo uniforme nel tempo. Un'applicazione progettata in modo scorretto produrrà un picco di il traffico a livelli sessanta volte normali all'inizio di ogni minuto.

Un'ottima soluzione potrebbe essere quella di impostare una seconda sveglia su un orario selezionato in modo casuale. Quando questo secondo allarme si attiva, l'applicazione chiama tutte le API di cui ha bisogno e memorizza che consentono di analizzare i dati e visualizzare i risultati. Quando l'applicazione vuole aggiornare il proprio display all'inizio del minuto, usa a risultati archiviati in precedenza anziché chiamare di nuovo l'API. Con questo approccio, le chiamate API sono distribuiti in modo uniforme nel tempo. Inoltre, le chiamate API non ritardano il rendering quando il display viene in fase di aggiornamento.

Oltre all'inizio del minuto, altri orari di sincronizzazione comuni devono essere non scelti come target sono all'inizio di un'ora e all'inizio di ogni giorno a mezzanotte.

Elaborazione delle risposte

Questa sezione illustra come estrarre questi valori in modo dinamico dalle risposte del servizio web.

I servizi web di Google Maps forniscono risposte facili da capire, ma non proprio facile da usare. Quando esegui una query, piuttosto che visualizzare un set di dati, probabilmente vorrai estrarre alcuni e i relativi valori. In genere, è consigliabile analizzare le risposte provenienti dal web servizio ed estrarre solo i valori che ti interessano.

Lo schema di analisi utilizzato dipende dal fatto che tu stia restituendo in XML o JSON. Risposte JSON, che sono già sotto forma di Oggetti JavaScript, possono essere elaborati all'interno di JavaScript sul cliente. Le risposte XML devono essere elaborate utilizzando un processore XML e un linguaggio di query XML per gestire gli elementi in formato XML. Utilizziamo XPath nella gli esempi riportati di seguito, poiché è comunemente supportata nell'elaborazione XML, librerie.

Elaborazione di XML con XPath

XML è un formato di informazioni strutturate relativamente maturo utilizzato per interscambio di dati. Sebbene non sia leggero come i file JSON, offre un supporto più linguistico e strumenti più solidi. Codice per l'elaborazione di XML in Java, ad esempio, è integrata javax.xml pacchetti.

Quando elabori le risposte XML, devi utilizzare un oggetto linguaggio di query per selezionare i nodi all'interno del documento XML, piuttosto che presupporre che gli elementi risiedano in posizioni assolute all'interno di markup XML. XPath è una sintassi del linguaggio per la descrizione univoca di nodi ed elementi all'interno di un documento XML. Le espressioni XPath consentono di identificare contenuti specifici all'interno del documento di risposta XML.

Espressioni XPath

Una certa familiarità con XPath aiuta notevolmente a sviluppare un solido schema di analisi. Questa sezione è incentrata su come gli elementi all'interno di un documento XML sono indirizzati con XPath, consentendoti gestire più elementi e costruire query complesse.

XPath utilizza le espressioni per selezionare gli elementi all'interno di un file XML utilizzando una sintassi simile a quella utilizzata per i percorsi delle directory. Queste espressioni identificano gli elementi all'interno di un documento XML che è un albero gerarchico simile a quello di un DOM. In genere, le espressioni XPath sono greedy, a indicare che corrisponderà a tutti i nodi che soddisfano i criteri forniti.

Utilizzeremo il seguente XML astratto per illustrare esempi:

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

Selezione dei nodi nelle espressioni

Le selezioni di XPath selezionano i nodi. Il nodo radice e l'intero documento. Selezioni questo nodo utilizzando l'espressione speciale "/". Tieni presente che la directory principale node non è il nodo di primo livello del tuo documento XML; in realtà si trova un livello al di sopra dell'elemento di primo livello e include li annotino.

I nodi degli elementi rappresentano i vari elementi all'interno del file XML struttura di documenti. Un elemento <WebServiceResponse>, ad esempio, rappresenta l'elemento di primo livello restituito servizio di esempio sopra riportato. Puoi selezionare i singoli nodi tramite assoluti o relativi, indicati dalla presenza o assenza di un "/" iniziale .

  • Percorso assoluto: "/WebServiceResponse/result" seleziona tutti i <result> nodi sono figli di <WebServiceResponse> nodo. (tieni presente che entrambi gli elementi discendono dalla directory principale nodo "/".)
  • Percorso relativo del contesto corrente: l'espressione "result" corrisponde a qualsiasi <result> nel contesto corrente. In genere, non dovresti preoccuparsi del contesto, perché di solito vengono elaborati di servizio tramite una singola espressione.

Ognuna di queste espressioni può essere aumentata mediante l'addizione di un percorso con caratteri jolly, indicato da una doppia barra ("//"). Questo carattere jolly indica che zero o più elementi possono corrispondere nel percorso intermedio. L'espressione XPath "//formatted_address", ad esempio, corrisponderà a tutti i nodi con quel nome nel documento corrente. L'espressione //viewport//lat trova tutte le corrispondenze Elementi <lat> che possono tracciare <viewport> come genitore.

Per impostazione predefinita, le espressioni XPath corrispondono a tutti gli elementi. Puoi limitare l'espressione in modo che corrisponda a un determinato elemento fornendo un predicato, racchiusa tra parentesi quadre ([]). XPath "/GeocodeResponse/result[2] restituisce sempre un secondo risultato, ad esempio.

Tipo di espressione
Nodo principale
Espressione XPath: "/"
Selezione:
    <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>
    
Percorso assoluto
Espressione XPath: "/WebServiceResponse/result"
Selezione:
    <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>
    
Percorso con carattere jolly
Espressione XPath: "/WebServiceResponse//location"
Selezione:
    <location>
     <lat>37.4217550</lat>
     <lng>-122.0846330</lng>
    </location>
    
Percorso con predicato
Espressione XPath: "/WebServiceResponse/result[2]/message"
Selezione:
    <message>The secret message</message>
    
Tutti gli elementi secondari diretti del primo result
Espressione XPath: "/WebServiceResponse/result[1]/*"
Selezione:
     <type>sample</type>
     <name>Sample XML</name>
     <location>
      <lat>37.4217550</lat>
      <lng>-122.0846330</lng>
     </location>
    
Il name di result il cui testo type è "sample."
Espressione XPath: "/WebServiceResponse/result[type/text()='sample']/name"
Selezione:
    Sample XML
    

È importante notare che quando selezioni gli elementi, selezioni i nodi, non solo il testo all'interno di questi oggetti. In genere, eseguire l'iterazione su tutti i nodi corrispondenti ed estrarre il testo. Tu possono anche corrispondere direttamente ai nodi di testo; consulta Nodi di testo qui sotto.

Tieni presente che XPath supporta anche i nodi degli attributi; ma tutti i servizi web di Google Maps forniscono elementi senza attributi, quindi la corrispondenza degli attributi non è necessaria.

Selezione del testo nelle espressioni

Il testo all'interno di un documento XML viene specificato nelle espressioni XPath tramite un operatore text node. Questo operatore "text()" indica l'estrazione di testo dal nodo indicato. Ad esempio: l'espressione XPath "//formatted_address/text()" che restituisce tutto il testo in <formatted_address> elementi.

Tipo di espressione
Tutti i nodi di testo (spazi vuoti inclusi)
Espressione XPath: "//text()"
Selezione:
    sample
    Sample XML

    37.4217550
    -122.0846330
    The secret message
    
Selezione del testo
Espressione XPath: "/WebServiceRequest/result[2]/message/text()"
Selezione:
    The secret message
    
Selezione sensibile al contesto
Espressione XPath: "/WebServiceRequest/result[type/text() = 'sample']/name/text()"
Selezione:
    Sample XML
    

In alternativa, puoi valutare un'espressione e restituire un insieme di nodi e quindi ripetere l'iterazione sul "set di nodi", estraendo il testo da ciascun nodo. Utilizziamo questo approccio nell'esempio riportato di seguito.

Per maggiori informazioni su XPath, consulta Specifica XPath W3C.

Valutazione di XPath in Java

Java supporta l'analisi dei dati XML e l'utilizzo delle espressioni XPath all'interno del pacchetto javax.xml.xpath.*. Per questo motivo, il codice campione in questa sezione utilizza Java per illustrano come gestire il codice XML e analizzare i dati delle risposte del servizio XML.

Per usare XPath nel tuo codice Java, devi prima creare un'istanza un'istanza di XPathFactory e richiama newXPath() in quella fabbrica per creare un oggetto XPath . Questo oggetto può quindi elaborare l'XML passato e XPath usando il metodo evaluate().

Quando valuti le espressioni XPath, assicurati di ripetere su qualsiasi possibile "set di nodi" che possono essere restituiti. Poiché questi vengono restituiti come nodi DOM nel codice Java, devi acquisire come valori multipli all'interno di un oggetto NodeList esegui l'iterazione sull'oggetto per estrarre qualsiasi testo o valore da questi nodi.

Il seguente codice illustra come creare un XPath assegnargli un file XML e un'espressione XPath e valutare espressione per stampare i contenuti pertinenti.

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