Linee guida HTTP

Questo documento descrive il funzionamento delle API di Google con implementazioni e versioni HTTP diverse. Se utilizzi una delle nostre librerie client generate o personalizzate (il nostro approccio consigliato per la maggior parte dei casi d'uso), non devi preoccuparti, poiché il codice fornito gestisce i problemi di basso livello della comunicazione con il server.

Tuttavia, se sei uno sviluppatore esperto e devi scrivere il tuo codice personalizzato per accedere direttamente all'interfaccia REST di un'API utilizzando una libreria client HTTP di terze parti a tua scelta, devi comprendere almeno alcune delle semantiche documentate qui (in base alla tua API scelta), nonché comprendere cosa viene fornito dalla tua libreria HTTP.

Utilizzo dei protocolli di rete (HTTP/*)

Questa sezione descrive i protocolli di rete supportati (in genere una versione di HTTP) che le API Cloud possono utilizzare per comunicare tra client e server e il modo in cui ti consigliamo di utilizzarli. Nella sezione di seguito esamineremo i dettagli della struttura delle richieste e delle risposte.

Semantica HTTP

Quando sviluppi il codice client dell'API, segui la semantica del protocollo HTTP standard. I proxy lato server o gli stack API possono supportare solo un sottoinsieme di funzionalità HTTP standard e anche le relative versioni compatibili con le versioni precedenti.

La semantica del protocollo HTTP che deve essere gestita dalle implementazioni lato server delle API è controllata dallo stack del server. Fai affidamento su queste semantiche solo se queste funzionalità sono documentate esplicitamente nell'ambito della specifica dell'API, come il supporto della memorizzazione nella cache.

Versioni HTTP

I client possono utilizzare qualsiasi protocollo HTTP/*, come consentito dalla piattaforma client o dalla rete lato client o come concordato con il proxy lato server. I protocolli supportati includono HTTP/1.0, HTTP/1.1, SPDY/*, HTTP/2 e QUIC.

Alcune funzionalità dell'API potrebbero essere supportate solo dalle versioni più recenti dei protocolli HTTP, come push del server e priorità; alcune sono completamente specificate solo con HTTP/2, come lo streaming full-duplex. Tieni presente le limitazioni delle diverse versioni HTTP se hai bisogno di una di queste funzionalità nell'ambito della specifica dell'API.

In genere consigliamo HTTP/2 per migliorare le prestazioni e la resilienza ai guasti della rete.

Canali

I canali fanno riferimento alle connessioni di rete L4 (socket TCP o UDP). Le applicazioni client non devono fare alcuna supposizione su come i canali vengono utilizzati in fase di runtime per gestire le richieste HTTP. In quasi tutti i casi, i canali vengono chiusi da proxy per conto del processo del server.

Per i client HTTP/1.1, riutilizza sempre le connessioni TCP (Connection: Keep-Alive); la libreria client HTTP gestirà probabilmente anche un pool di connessioni per un rendimento migliore. Non eseguire il riavvolgimento delle richieste sulla stessa connessione TCP. Per ulteriori informazioni, consulta HTTP e TCP.

I browser moderni supportano tutti SPDY/*, HTTP/2 o QUIC, che eseguono il multiplexing delle richieste su un unico canale. Il limite di connessioni tradizionale (2-10) non dovrebbe mai essere un problema, tranne quando l'implementazione del server limita il numero di richieste HTTP simultanee da un singolo client, ad esempio 100 stream HTTP/2 su una singola origine.

HTTPS

I client possono accedere a un'API tramite HTTPS o HTTP, come supportato dalla specifica dell'API. La negoziazione TLS e le versioni TLS sono trasparenti per le applicazioni client. Per impostazione predefinita, le API Google accettano solo il traffico HTTPS.

Formati di richiesta/risposta

URL di richiesta

La mappatura JSON-REST supporta i dati della richiesta codificati tramite URL e il corpo della richiesta e della risposta HTTP utilizza application/json come Content-Type.

Il corpo HTTP utilizza un array JSON per supportare i metodi RPC in streaming e l'array JSON può contenere un numero qualsiasi di messaggi JSON o un messaggio JSON con stato di errore.

URL di richiesta lunghi

L'URL ha una limitazione pratica della lunghezza, in genere impostata su 16 KB per impostazione predefinita, anche se questo può variare a seconda del server. Se la tua API utilizza richieste GET con URL che superano questa lunghezza, le richieste potrebbero non raggiungere il server API di destinazione e verranno rifiutate da Google Front End (GFE) con il messaggio di errore Your client has issued a malformed or illegal request.

Per aggirare la limitazione, il codice client deve utilizzare una richiesta POST con il valore application/x-www-form-urlencoded per il Content-Type e l'intestazione HTTP X-HTTP-Method-Override: GET. Questo approccio funziona anche per le richieste DELETE.

Metodi HTTP (verbi)

Se gli URL delle richieste seguono il modello REST, i relativi metodi HTTP sono specificati nell'ambito della specifica dell'API. In particolare, ogni metodo dell'API deve essere conforme ai requisiti del protocollo HTTP in base al verbo HTTP specifico a cui il metodo dell'API viene mappato. Per maggiori dettagli, consulta la specifica del Hypertext Transfer Protocol e l'RFC del metodo PATCH.

I metodi sicuri, come HTTP GET e HEAD, non devono rappresentare un'azione diversa dal recupero. Nello specifico, HTTP GET deve essere considerato sicuro e non deve avere effetti collaterali visibili dal client.

L'idempotenza in HTTP significa che gli effetti collaterali di più richieste identiche sono gli stessi di una singola richiesta. GET, PUT e DELETE sono i metodi HTTP idempotenti pertinenti alla guida di stile. Tieni presente che l'idempotenza è espressa solo in termini di effetti collaterali del server e non specifica nulla sulla risposta. In particolare, DELETE per le risorse non esistenti deve restituire 404 (Not Found).

HTTP POST e PATCH non sono sicuri né idempotenti. (PATCH è stato introdotto nell'RFC 5789)

Verbo HTTP Sicuro Idempotente
GET
PUT  
DELETE  
POST  
PATCH  

Formati del payload

  • La richiesta e la risposta devono condividere lo stesso Content-Type, tranne quando la richiesta è un GET o un POST con un corpo "application/x-www-form-urlencoded".

  • JSON è supportato dal tipo MIME application/json. La mappatura da proto3 a JSON è specificata formalmente in JSON Mapping.

  • I parametri dei moduli (POST) possono essere utilizzati al posto dei parametri di ricerca dell'URL (GET), seguendo la stessa regola di mappatura in stile REST per mappare i campi della richiesta ai parametri di query. Il Content-Type supportato è application/x-www-form-urlencoded.

Streaming

Half-duplex e full-duplex

HTTP è un protocollo di richiesta-risposta che consente di inviare il corpo della richiesta o della risposta su diversi trasporti orientati allo stream, come TCP (HTTP/1.x) o le relative varianti multiplexate (SPDY, HTTP/2, QUIC).

In qualità di sviluppatore client, la tua applicazione può produrre il corpo della richiesta in modalità di streaming, ovvero client-streaming. Analogamente, l'applicazione può anche consumere il corpo della risposta in modalità di streaming, ovvero server-streaming.

Tuttavia, la specifica HTTP non specifica se un server è autorizzato a trasmettere in streaming il corpo della risposta (ad eccezione delle risposte di errore) quando il corpo della richiesta è ancora in stato pending. Questa semantica è nota come streaming full-duplex. Sebbene molti software client/server/proxy HTTP consentano lo streaming full-duplex, anche per HTTP/1.1, per evitare problemi di interoperabilità le API cloud basate su HTTP sono limitate solo allo streaming half-duplex.

Per impostazione predefinita, i metodi di streaming bidirezionale nelle API Cloud presuppongono la semantica full-duplex. In altre parole, non è sicuro utilizzare HTTP per invocare un metodo di questo tipo. Se un metodo di streaming è solo half-duplex (come imposto dal server), il documento dell'API deve specificare chiaramente il comportamento half-duplex.

Per i client del browser, la semantica HTTP standard è ulteriormente limitata dalle API di rete del browser. Attualmente i browser supportano solo lo streaming del server (che generalmente rispetta il framing a livello di trasporto) tramite XHR o Fetch. L'API Fetch utilizza gli stream WHATWG.

A causa delle limitazioni del browser, le API Cloud che richiedono il supporto del browser devono evitare lo streaming client e lo streaming full-duplex oppure fornire un'API separata specificamente per i client browser.

In generale, lo streaming client su internet è meno utile dello streaming server. Questo perché l'utilizzo dello streaming client spesso porta a un servizio stateful, che influisce negativamente sul bilanciamento del carico e rende il sistema più vulnerabile a guasti o attacchi. Lo streaming dal server, invece, può essere utile perché può ridurre notevolmente la latenza sulle reti con ritardi RTT lunghi.

Codifica dei messaggi

I messaggi JSON durante lo streaming vengono codificati come array di messaggi JSON. Il corpo della richiesta o della risposta rimarrà un tipo MIME JSON valido.

Esempio di codifica dello stream del client:

1 <length> <message-bytes> 1 <length> <message-bytes>   EOF

Esempio di codifica dello stream del server:

1 <length> <message-bytes>   2 <length> <status-bytes> EOF

Codifica a livello di cavo: la definizione di StreamBody è significativa solo per l'allocazione degli ID tag per il campo "messages" e "status". Verrà codificata con varint con 1-2 byte per i messaggi normali, quindi il sovraccarico totale della codifica è di 2-3 byte per messaggio.

Per supportare gli stream con codifica base64 è necessario un campo di riempimento facoltativo:

message StreamBody {
  repeated bytes message = 1;
  google.rpc.Status status = 2;
  repeated bytes padding = 15;   // max one-byte tag-id: xxx01111
}

I messaggi di errore devono essere aggiunti come ultimo elemento dell'array JSON o protobuf, nello stesso formato dei messaggi normali.

Gestione dello stato

Il comportamento di chiusura parziale è ben definito in qualsiasi versione HTTP per consentire a un client o a un server di segnalare all'altra estremità il completamento del corpo.

In particolare, il codice client è libero di completare la richiesta mentre è ancora in attesa della risposta. Analogamente, un client potrebbe visualizzare una risposta completata quando il corpo della richiesta è ancora in fase di scrittura sul server. Lo standard HTTP si aspetta che il client interrompa o completi la richiesta quando una risposta viene completata in modo imprevisto, in genere con uno stato di errore. In altre parole, in condizioni normali il server non deve completare una risposta quando il client sta ancora inviando la richiesta.

Annullamento

Il supporto dell'annullamento consente a un client di interrompere una richiesta quando la richiesta o la risposta è ancora in attesa.

Non è disponibile un supporto affidabile per l'annullamento per i client HTTP/1.*, in quanto un client è libero di chiudere una connessione TCP dopo il completamento della richiesta senza abortire la transazione richiesta/risposta. Un FIN TCP, in HTTP/1.1, non deve essere interpretato come un annullamento, anche quando la connessione è contrassegnata come keep-alive (Connection: Keep-Alive).

Tuttavia, dopo che il client ha chiuso la connessione TCP, se il server tenta di scrivere dati sul client, verrà generato un RST, che può attivare un annullamento.

Tieni inoltre presente che l'annullamento è un problema anche per le API non in streaming. Questo accade soprattutto quando la risposta prevede un polling lungo e la connessione potrebbe rimanere inattiva per un periodo prolungato.

L'annullamento esplicito è supportato con SPDY, HTTP/2 e QUIC, in particolare con il messaggio di allontanamento.

Keep-alive

Il supporto del keep-alive consente a un client o a un server di rilevare un peer non riuscito, anche in caso di perdita di pacchetti o errori di rete.

In HTTP/1.1 non è supportato il keep-alive perché il keep-alive TCP non è un approccio valido.

QUIC o HTTP/2 offrono messaggi di controllo speciali allo scopo di implementare il supporto keep-alive da parte delle applicazioni, inclusi i browser.

Tuttavia, il rilevamento affidabile di keep-alive e errori richiederà probabilmente una libreria client con il supporto lato server necessario: lo streaming di lunga durata su internet è spesso soggetto a errori se si utilizza HTTP di base come protocollo di comunicazione.

Controllo del flusso

Il supporto del controllo flusso richiede che il client propaghi gli eventi di controllo flusso a livello di trasporto all'applicazione client. Il meccanismo effettivo dipende dall'impostazione dell'API client HTTP utilizzata dall'applicazione client. Ad esempio, per consentire alle applicazioni di gestire e rispettare gli eventi di controllo del flusso, è necessario disporre di letture e scritture bloccanti o letture e scritture non bloccanti con supporto esplicito per il controllo del flusso per evitare il sovraccarico del client o del server.

HTTP/1.1 si basa sul controllo del flusso TCP.

SPDY e HTTP/2 hanno un proprio controllo del flusso a livello di stream, che è inoltre soggetto al controllo del flusso TCP a livello di connessione poiché le richieste vengono multiplexate su una singola connessione TCP.

QUIC funziona su UDP e quindi gestisce il controllo del flusso completamente autonomamente.