Linee guida HTTP

Questo documento spiega come le API di Google funzionano con varie versioni e implementazioni HTTP. Se utilizzi le nostre librerie client generate o create manualmente (l'approccio consigliato per la maggior parte dei casi d'uso), non devi preoccuparti di questi dettagli. Le librerie gestiscono automaticamente la comunicazione di basso livello con il server.

Se sei uno sviluppatore esperto che scrive codice personalizzato per accedere all'interfaccia REST di un'API utilizzando un client HTTP di terze parti, devi comprendere i concetti pertinenti documentati qui, insieme alle funzionalità fornite dalla libreria HTTP scelta.

Utilizzare i protocolli di rete (HTTP/*)

Questa sezione descrive i protocolli di rete supportati (in genere una versione di HTTP) che le API di Google possono utilizzare per comunicare tra client e server e come consigliamo di utilizzarli.

Semantica HTTP

Quando sviluppi il codice client API, segui la semantica standard del protocollo HTTP . I proxy lato server o gli stack API potrebbero supportare solo un sottoinsieme delle funzionalità HTTP standard e potrebbero anche supportare le relative versioni con compatibilità 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 questa semantica solo se queste funzionalità sono documentate esplicitamente come parte della specifica API, ad esempio 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 negoziato con il proxy lato server. I protocolli supportati includono HTTP/1.1, HTTP/2 e HTTP/3 (QUIC). Il supporto legacy per HTTP/1.0 è fortemente sconsigliato.

Alcune funzionalità API potrebbero essere supportate solo dalle versioni più recenti dei protocolli HTTP; alcune sono specificate completamente solo con HTTP/2 e HTTP/3, ad esempio lo streaming multiplex full-duplex. Tieni presente le limitazioni delle diverse versioni HTTP se richiedi una di queste funzionalità come parte della specifica API. Tieni presente che le funzionalità precedenti, come HTTP/2 Server Push, sono obsolete e non sono supportate dai client web moderni.

In genere, consigliamo HTTP/3 o HTTP/2 per prestazioni migliori, riduzione del blocco head-of-line e maggiore resilienza agli errori di rete.

Canali

I canali si riferiscono alle connessioni di rete di livello 4, che in genere sono socket TCP per HTTP/1.1 e HTTP/2 e socket UDP per HTTP/3 (QUIC). Le applicazioni client non devono fare ipotesi su come vengono gestiti i canali end-to-end, poiché le connessioni vengono quasi sempre terminate dai proxy Google Front End (GFE) per conto del processo server.

Client HTTP/1.1: se utilizzi HTTP/1.1, riutilizza sempre le connessioni TCP (Connection: Keep-Alive). In genere, le librerie client HTTP gestiscono un pool di connessioni per facilitare il riutilizzo. Evita il pipelining HTTP sulle connessioni HTTP/1.1; è scarsamente supportato e può causare problemi. Per ulteriori informazioni, consulta HTTP e TCP.

Client HTTP/2 e HTTP/3: i client e i browser moderni utilizzano principalmente HTTP/2 o HTTP/3. Entrambi i protocolli supportano il multiplexing, consentendo l'esecuzione simultanea di più richieste e risposte su una singola connessione.

  • HTTP/2: utilizza una singola connessione TCP per origine.
  • HTTP/3: utilizza una singola connessione QUIC su UDP per origine. QUIC integra la crittografia TLS, il controllo della congestione e la gestione delle connessioni, spesso fornendo vantaggi come una configurazione più rapida della connessione (0-RTT o 1-RTT) e l'immunità al blocco head-of-line TCP tra i flussi.

Con HTTP/2 e HTTP/3, i limiti del browser sul numero di connessioni TCP parallele a un singolo host (ad esempio, 2-10) non sono più un problema di prestazioni primario. Tuttavia, tieni presente che i server (o i proxy come GFE) possono comunque applicare limiti al numero massimo di flussi simultanei all'interno di una singola connessione HTTP/2 o HTTP/3. In questo modo si evita il sovraccarico e si garantisce un utilizzo equo delle risorse (ad esempio, limitando a 100 le richieste o i flussi simultanei per connessione).

HTTPS

I client possono accedere a un'API utilizzando HTTPS o HTTP, come supportato dalla specifica 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 e risposta

Questa sezione descrive la struttura delle interazioni API, incluso l'utilizzo di dati codificati tramite URL, metodi HTTP specifici per le azioni RESTful e formati di payload basati su JSON.

URL di richiesta

Il mapping JSON-REST supporta i dati di 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 di 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 potrebbe 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 un Content-Type di 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 delle richieste seguono il modello REST, i relativi metodi HTTP vengono specificati come parte della specifica API. In particolare, ogni metodo API deve rispettare i requisiti del protocollo HTTP in base al verbo HTTP specifico a cui viene mappato il metodo API. Per ulteriori informazioni, consulta la specifica del protocollo di trasferimento ipertestuale e la RFC del metodo PATCH.

I metodi sicuri, come `GET` e `HEAD` HTTPGET e HEAD, non devono rappresentare un'azione diversa dal recupero. In particolare, GET HTTP deve essere considerato sicuro e non deve avere effetti collaterali visibili al 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 viene espressa solo in termini di effetti collaterali lato server e non specifica nulla sulla risposta. In particolare, DELETE per le risorse inesistenti deve restituire 404 (Not Found).

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

Verbo HTTP Sicuro Idempotente
GET
PUT  
DELETE  
POST  
PATCH  

Formati di 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 con il tipo MIME application/json. Il mapping da proto3 a JSON è specificato formalmente in Mapping JSON.

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

Streaming

Questa sezione descrive in dettaglio come le API di Google gestiscono lo streaming client e server, affrontando in particolare i vincoli della comunicazione half-duplex rispetto a quella full-duplex e i requisiti di codifica per i messaggi JSON in streaming.

Half-duplex e full-duplex

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

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

Tuttavia, la specifica HTTP non specifica se un server è autorizzato a 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 programmi 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. Ciò significa che non è sicuro utilizzare HTTP per richiamare un metodo di questo tipo. 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. I browser supportano il server-streaming (che in genere rispetta il framing a livello di trasporto) utilizzando XHR o Fetch. L'API Fetch utilizza i flussi whatwg.

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

In generale, il client-streaming su internet è meno utile del server-streaming. Questo perché l'utilizzo del client-streaming spesso porta a un servizio con stato, che influisce negativamente sul bilanciamento del carico e rende il sistema più vulnerabile a errori o attacchi. Il server-streaming, d'altra parte, può essere utile in quanto può ridurre significativamente la latenza sulle reti con ritardi RTT elevati.

Codifica di messaggi

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

Esempio di codifica del flusso client:

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

Esempio di codifica del flusso server:

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

Codifica a livello di rete: la definizione di StreamBody è significativa solo nella sua allocazione degli ID tag per i campi "messages" e "status" <length> che verranno codificati con varint con 1-2 byte per i messaggi normali, quindi il sovraccarico di codifica totale è di 2-3 byte per messaggio.

È necessario un campo di riempimento facoltativo per supportare i flussi con codifica 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 dello stato

Il comportamento di chiusura parziale è ben definito in qualsiasi versione HTTP per un client o un server per segnalare all'altra estremità che il corpo è stato completato.

In particolare, il codice client è libero di completare la richiesta mentre è ancora in attesa della risposta. Allo stesso modo, un client potrebbe visualizzare una risposta completata mentre il corpo della richiesta è ancora in fase di scrittura sul server. Lo standard HTTP prevede che il client interrompa o completi la richiesta quando una risposta viene completata in modo imprevisto, in genere con uno stato di errore. Ciò significa che, in condizioni normali, il server non deve completare una risposta mentre 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.*, poiché un client è libero di chiudere una connessione TCP dopo che la richiesta è stata completata senza interrompere la transazione di richiesta o risposta. Un TCP FIN, 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 chiude la connessione TCP, se il server tenta di scrivere dati sul client, verrà generato un RST, che può attivare un annullamento.

Tieni presente che l'annullamento è un problema anche per le API non in streaming. Questo è particolarmente vero quando la risposta prevede un long polling e quindi la connessione potrebbe rimanere inattiva per un periodo prolungato.

L'annullamento esplicito è supportato con SPDY, HTTP/2 e QUIC, in particolare con il messaggio go-away.

Keep-alive

Il supporto 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.

Non è disponibile il supporto keep-alive in HTTP/1.1, poiché il keep-alive TCP non è un approccio praticabile.

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 keep-alive affidabile e il rilevamento degli errori richiederanno probabilmente una libreria client con il supporto lato server necessario: lo streaming a lunga durata su internet è spesso soggetto a errori quando si utilizza 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, sono necessarie scritture e letture bloccanti o letture e scritture non bloccanti con supporto esplicito del controllo del flusso per consentire alle applicazioni di gestire e rispettare gli eventi di controllo del flusso, al fine di 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 multiplex su una singola connessione TCP.

QUIC viene eseguito su UDP e pertanto gestisce il controllo del flusso in modo completamente autonomo.