Linee guida HTTP

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

Tuttavia, se sei uno sviluppatore esperto e hai bisogno di scrivere codice personalizzato per accedere direttamente all'interfaccia REST di un'API utilizzando una libreria client HTTP di terze parti a tua scelta, dovresti conoscere almeno alcune delle semantiche qui documentate (in relazione all'API scelta), oltre a capire ciò che 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 come ti consigliamo di utilizzarli. Esamineremo i dettagli di come sono strutturate le richieste e le risposte nella prossima sezione qui sotto.

semantica HTTP

Durante lo sviluppo del codice client 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 potrebbero anche supportare 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 di server. Fai affidamento su questa semantica solo se queste funzionalità sono documentate esplicitamente come parte delle specifiche dell'API, ad esempio il supporto della memorizzazione nella cache.

Versioni HTTP

I client possono utilizzare qualsiasi protocollo HTTP/*, consentito dalla piattaforma client o dalla rete lato client, oppure negoziato 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 la modalità push server e le priorità; alcune sono specificate completamente solo con HTTP/2, ad esempio lo streaming full-duplex. Tieni presente le limitazioni delle diverse versioni HTTP se hai bisogno di una di queste funzionalità nell'ambito delle specifiche dell'API.

Generalmente consigliamo HTTP/2 per ottenere prestazioni migliori e resilienza agli errori di rete.

Canali

I canali fanno riferimento alle connessioni di rete L4 (prese TCP o UDP). Le applicazioni client non devono fare ipotesi sul modo in cui i canali vengono utilizzati nel runtime per gestire le richieste HTTP. In quasi tutti i casi, i canali vengono chiusi da proxy per conto del processo server.

Per i client HTTP/1.1, riutilizza sempre le connessioni TCP (connessione: Keep-Alive); è probabile che la libreria client HTTP gestirà anche un pool di connessioni per migliorare le prestazioni. Non eseguire la pipeline delle richieste sulla stessa connessione TCP. Per ulteriori informazioni, consulta HTTP e TCP.

I browser moderni parlano tutti SPDY/*, HTTP/2 o QUIC, che eseguono il multiplex delle richieste su un singolo 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 in parallelo da un singolo client, ad esempio 100 flussi HTTP/2 su una singola origine.

HTTPS

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

Formati di richiesta/risposta

URL delle richieste

Il mapping REST JSON supporta i dati delle richieste con codifica 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 trasmessi 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 un limite di lunghezza pratico, in genere compreso tra 2 kB e 8 kB. È applicato da alcuni browser e proxy. Se l'API utilizza richieste GET con URL che superano il limite di lunghezza, tali richieste potrebbero essere rifiutate dai browser. Per aggirare questo limite, il codice client deve utilizzare una richiesta POST con Content-Type application/x-www-form-urlencoded insieme all'intestazione HTTP X-HTTP-Method-Override: GET. Questo approccio funziona anche per le richieste DELETE.

Metodi HTTP (verbi)

Se gli URL della richiesta seguono il modello REST, i relativi metodi HTTP vengono specificati come parte della specifica API. In particolare, ogni metodo API deve soddisfare i requisiti del protocollo HTTP in base al verbo HTTP specifico a cui viene mappato il metodo API. Per i dettagli, consulta la specifica Hypertext Transfer Protocol e la RFC PATCH Method.

I metodi sicuri, come HTTP GET e HEAD, non devono rappresentare un'azione diversa dal recupero. In particolare, HTTP GET deve essere considerato sicuro e non deve presentare effetti collaterali visibili al client.

L'idempotenza in HTTP indica 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 per la guida di stile. Tieni presente che l'idempotenza viene 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 né sicuri né idempotenti. (PATCH è stato introdotto in RFC 5789)

Verbo HTTP Sicuro IDempotente
GET
PUT  
DELETE  
POST  
PATCH  

Formati 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. Il mapping da proto3 a JSON viene specificato formalmente in JSON Mapping.

  • Puoi utilizzare i parametri del modulo (POST) al posto dei parametri di ricerca dell'URL (GET), seguendo la stessa regola di mappatura in stile REST per mappare i campi di richiesta ai parametri di query. Il valore di Content-Type supportato è application/x-www-form-urlencoded.

Flussi di dati

Half-duplex e full-duplex

HTTP è un protocollo di richiesta-risposta che consente di inviare il corpo della richiesta o della risposta tramite diversi trasporti orientati al flusso come TCP (HTTP/1.x) o le sue varianti multiplex (SPDY, HTTP/2, QUIC).

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

Tuttavia, la specifica HTTP non specifica se a un server è consentito eseguire lo streaming del corpo della risposta (ad eccezione delle risposte di errore) quando il corpo della richiesta è ancora in attesa. 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 al solo streaming half-duplex.

Per impostazione predefinita, i metodi di streaming bidi nelle API Cloud presuppongono la semantica full-duplex. Ciò significa che non è sicuro utilizzare HTTP per richiamare questo metodo. Se un metodo di streaming è solo half-duplex (come applicato dal server), il documento API deve specificare chiaramente il comportamento half-duplex.

Per i client browser, la semantica HTTP standard è ulteriormente vincolata dalle API di rete del browser. Attualmente i browser supportano solo il flusso di server (che generalmente rispetta i frame a livello di trasporto) tramite XHR o Fetch. L'API Fetch utilizza i streaming whatwg.

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

In generale, l'esecuzione di flussi di dati client su internet è meno utile dell'esecuzione di flussi di dati su server. Questo perché l'utilizzo del flusso di client spesso porta a un servizio stateful, che influisce negativamente sul bilanciamento del carico e rende il sistema più vulnerabile a errori o attacchi. Il flusso di dati del server, d'altra parte, può essere utile in quanto può ridurre notevolmente la latenza rispetto alle reti con lunghi ritardi RTT.

Codifica dei messaggi

I messaggi JSON durante il flusso di dati sono codificati come un array di messaggi JSON. Il corpo della richiesta o della risposta rimarrà come tipo MIME JSON valido.

Esempio di codifica dello stream client:

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

Esempio di codifica dei flussi di server:

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

Codifica a livello di cavo: la definizione di StreamBody è significativa solo nella sua allocazione degli ID tag per il campo "messages" e lo "status" saranno codificati con 1-2 byte per i messaggi normali, quindi l'overhead di codifica totale è di 2-3 byte per messaggio.

È necessario un campo di spaziatura interna facoltativo per supportare gli stream codificati in base64:

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 statale

Il comportamento di chiusura a metà è ben definito in qualsiasi versione HTTP per un client o un server per segnalare all'altra parte che il corpo è completo.

In particolare, il codice client può completare la richiesta quando è ancora in attesa della risposta. Analogamente, un client può vedere una risposta completata quando il corpo della richiesta è ancora in fase di scrittura nel server. Lo standard HTTP si aspetta che il client interrompa o completi la richiesta quando una risposta viene completata in modo imprevisto, solitamente con uno stato di errore. Ciò significa che, in condizioni normali, il server non deve completare una risposta quando il client continua a inviare la richiesta.

Annullare l'abbonamento

L'assistenza per l'annullamento consente a un client di interrompere una richiesta quando la richiesta o la risposta è ancora in attesa.

Non esiste un supporto affidabile per l'annullamento per i client HTTP/1.*, poiché un client è libero di chiudere una connessione TCP dopo che la richiesta è stata completata senza interrompere 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 (Connessione: Keep-Alive).

Tuttavia, dopo che il client ha chiuso la connessione TCP, se il server tenta di scrivere dati al 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 è particolarmente quando la risposta prevede un lungo polling e quindi la connessione può rimanere inattiva per un periodo prolungato.

La cancellazione esplicita è supportata con SPDY, HTTP/2 e QUIC, in particolare con il messaggio go-away.

Keep-alive

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

Non esiste un supporto keep-alive in HTTP/1.1 poiché il keep-alive TCP non è un approccio attuabile.

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

Tuttavia, un keep-alive e un rilevamento degli errori affidabili richiedono probabilmente una libreria client con il supporto lato server necessario: lo streaming di lunga durata su internet è spesso soggetto a errori quando si fa affidamento su HTTP di base come protocollo di comunicazione.

Controllo del flusso

Il supporto del controllo del flusso richiede che il client propaghi gli eventi di controllo del flusso a livello di trasporto all'applicazione client. Il meccanismo effettivo dipende dallo stile dell'API client HTTP utilizzata dall'applicazione client. Ad esempio, devi bloccare le operazioni di scrittura e lettura, oppure le operazioni di lettura e scrittura non bloccanti con un supporto esplicito per il controllo del flusso, affinché le applicazioni possano gestire e rispettare gli eventi di controllo del flusso, in modo da 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 flusso, che è ulteriormente soggetto al controllo del flusso TCP a livello di connessione poiché le richieste vengono multiplexate su una singola connessione TCP.

QUIC viene eseguito su UDP e, di conseguenza, gestisce il controllo del flusso in modo autonomo.