Consignes sur HTTP

Il est important de comprendre comment les API Google fonctionnent avec différentes versions et implémentations HTTP si vous écrivez du code personnalisé qui accède à l'interface REST d'une API à l'aide d'un client HTTP tiers. Pour la plupart des charges de travail, utilisez plutôt les bibliothèques clientes recommandées par Google, qui gèrent automatiquement la communication de bas niveau avec le serveur décrite dans ce document.

Travailler avec des protocoles de communication (HTTP/*)

Cette section décrit les protocoles de communication compatibles (généralement une version de HTTP) que les API Google peuvent utiliser pour communiquer entre les clients et les serveurs, et explique comment nous vous recommandons de les utiliser.

Sémantique HTTP

Lors du développement du code client API, respectez la sémantique du protocole HTTP standard. Les proxys côté serveur ou les piles d'API ne sont peut-être compatibles qu'avec un sous-ensemble des fonctionnalités HTTP standard, et peuvent également être compatibles avec leurs versions rétrocompatibles.

La sémantique du protocole HTTP qui doit être gérée par les implémentations côté serveur des API est contrôlée par la pile de serveurs. Ne vous fiez à cette sémantique que si ces fonctionnalités sont explicitement documentées dans le cadre des spécifications de l'API, telles que la disponibilité de la mise en cache.

Versions HTTP

Les clients peuvent utiliser n'importe quel protocole HTTP/*, comme autorisé par la plate-forme cliente ou leur réseau côté client, ou comme négocié avec le proxy côté serveur. Les protocoles compatibles incluent HTTP/1.1, HTTP/2 et HTTP/3 (QUIC). La compatibilité héritée avec HTTP/1.0 est fortement déconseillée.

Certaines fonctionnalités d'API ne sont peut-être compatibles qu'avec les versions plus récentes des protocoles HTTP. Certaines ne sont entièrement spécifiées qu'avec HTTP/2 et HTTP/3, comme le streaming multiplexé full-duplex. Tenez compte des limites des différentes versions HTTP si vous avez besoin de l'une de ces fonctionnalités dans le cadre des spécifications de l'API. Notez que les anciennes fonctionnalités telles que HTTP/2 Server Push sont obsolètes et ne sont pas compatibles avec les clients Web modernes.

En général, nous recommandons HTTP/3 ou HTTP/2 pour de meilleures performances, une réduction du blocage en tête de ligne et une plus grande résilience aux défaillances réseau.

Canaux

Les canaux font référence aux connexions réseau de couche 4, qui sont généralement des sockets TCP pour HTTP/1.1 et HTTP/2, et des sockets UDP pour HTTP/3 (QUIC). Les applications clientes ne doivent pas faire d'hypothèses sur la manière dont les canaux sont gérés de bout en bout, car les connexions sont presque toujours interrompues par les proxys Google Front End (GFE) au nom du processus serveur.

Clients HTTP/1.1 : si vous utilisez HTTP/1.1, réutilisez toujours les connexions TCP (Connection: Keep-Alive). Les bibliothèques clientes HTTP gèrent généralement un pool de connexions pour faciliter la réutilisation. Évitez le pipeline HTTP sur les connexions HTTP/1.1. Il est mal pris en charge et peut entraîner des problèmes. Pour en savoir plus, consultez HTTP et TCP.

Clients HTTP/2 et HTTP/3 : les clients et navigateurs modernes utilisent principalement HTTP/2 ou HTTP/3. Les deux protocoles sont compatibles avec le multiplexage, ce qui permet à plusieurs requêtes et réponses d'être en cours simultanément sur une seule connexion.

  • HTTP/2 : utilise une seule connexion TCP par origine.
  • HTTP/3 : utilise une seule connexion QUIC via UDP par origine. QUIC intègre le chiffrement TLS, le contrôle de la congestion et la gestion des connexions, ce qui offre souvent des avantages tels qu'une configuration de connexion plus rapide (0-DAR ou 1-DAR) et une immunité au blocage en tête de ligne TCP sur les flux.

Avec HTTP/2 et HTTP/3, les limites du navigateur concernant le nombre de connexions TCP parallèles à un seul hôte (par exemple, 2 à 10) ne sont plus un problème de performances majeur. Toutefois, sachez que les serveurs (ou les proxys tels que GFE) peuvent toujours appliquer des limites au nombre maximal de flux simultanés dans une seule connexion HTTP/2 ou HTTP/3. Cela évite la surcharge et garantit une utilisation équitable des ressources (par exemple, en limitant les requêtes ou flux simultanés par connexion à 100).

HTTPS

Les clients peuvent accéder à une API à l'aide de HTTPS ou HTTP, comme indiqué dans les spécifications de l'API. La négociation TLS et les versions TLS sont transparentes pour les applications clientes. Par défaut, les API Google acceptent uniquement le trafic HTTPS.

Formats de requête et de réponse

Cette section décrit la structure des interactions avec l'API, y compris l'utilisation de données encodées dans l'URL, de méthodes HTTP spécifiques pour les actions RESTful et de formats de charge utile basés sur JSON.

URL de requête

Le mappage JSON-REST est compatible avec les données de requête encodées dans l'URL, et le corps de la requête et de la réponse HTTP utilise application/json comme Content-Type.

Le corps HTTP utilise un tableau JSON pour prendre en charge les méthodes RPC en streaming. Le tableau JSON peut contenir n'importe quel nombre de messages JSON ou un message JSON d'état d'erreur.

URL de requête longues

L'URL est limitée en longueur, généralement définie sur 16 Ko par défaut, bien que cela puisse varier en fonction du serveur. Si votre API utilise des requêtes GET avec des URL qui dépassent cette longueur, les requêtes risquent de ne pas atteindre le serveur d'API de destination et seront rejetées par Google Front End (GFE) avec le message d'erreur Your client has issued a malformed or illegal request.

Pour contourner cette limite, le code client doit utiliser une requête POST avec un Content-Type application/x-www-form-urlencoded ainsi que l'en-tête HTTP X-HTTP-Method-Override: GET. Cette approche fonctionne également pour les requêtes DELETE.

Méthodes HTTP (verbes)

Si les URL de requête suivent le modèle REST, leurs méthodes HTTP sont spécifiées dans le cadre de la spécification de l'API. En particulier, chaque méthode d'API doit respecter les exigences du protocole HTTP en fonction du verbe HTTP spécifique auquel la méthode d'API est mappée. Pour en savoir plus, consultez la spécification du protocole de transfert hypertexte et la RFC de la méthode PATCH.

Les méthodes sûres, telles que HTTP GET et HEAD, ne doivent pas représenter une action autre que la récupération. HTTP GET doit en particulier être considérée comme sûre et ne doit avoir aucun effet secondaire visible par le client.

L'idempotence dans HTTP signifie que les effets secondaires de plusieurs requêtes identiques sont les mêmes que pour une requête unique. GET, PUT et DELETE sont les méthodes HTTP idempotentes pertinentes pour le guide de style. Notez que l'idempotence n'est exprimée qu'en termes d'effets secondaires sur le serveur et ne spécifie rien à propos de la réponse. En particulier, DELETE pour les ressources inexistantes doit renvoyer 404 (Not Found).

Les méthodes HTTP POST et PATCH ne sont ni sûres, ni idempotentes. (PATCH a été introduit dans le protocole RFC 5789.)

Verbe HTTP Sûr Idempotent
GET Oui Oui
PUT   Oui
DELETE   Oui
POST  
PATCH  

Formats de charge utile

  • La requête et la réponse doivent partager le même Content-Type, sauf lorsque la requête est une requête GET ou POST avec un corps "application/x-www-form-urlencoded".

  • JSON est compatible avec le type MIME application/json. Le mappage de proto3 et JSON est spécifié de façon formelle dans la section dédiée au mappage JSON.

  • Les paramètres de formulaire (POST) peuvent être utilisés à la place des paramètres de requête d'URL (GET), en suivant la même règle de mappage de style REST pour mapper les champs de requête aux paramètres de requête. Le Content-Type accepté est application/x-www-form-urlencoded.

Streaming

Cette section explique comment les Google APIs gèrent le streaming client et serveur, en abordant plus particulièrement les contraintes de la communication half-duplex par rapport à la communication full-duplex et les exigences d'encodage pour les messages JSON en streaming.

Half-duplex par rapport à full-duplex

HTTP est un protocole de requête-réponse qui permet à son corps de requête ou de réponse d'être distribué via différents transports orientés flux en continu, tels que TCP (HTTP/1.x) ou ses variantes multiplexées (SPDY, HTTP/2, QUIC).

En tant que développeur client, votre application peut générer le corps de la requête en mode de traitement par flux c'est-à-dire en diffusion en continu sur un client. De même, l'application peut également consommer le corps de la réponse en mode de traitement par flux, c'est-à-dire en diffusion en continu sur un serveur.

Toutefois, la spécification HTTP n'indique pas si un serveur est autorisé à diffuser en continu le corps de la réponse (à l'exception des réponses d'erreur) lorsque le corps de la requête est toujours en attente. Cette sémantique est appelée streaming full-duplex. Bien que de nombreux logiciels client/serveur/proxy HTTP autorisent le streaming full-duplex, même pour HTTP/1.1, afin d'éviter tout problème d'interopérabilité, les API cloud basées sur HTTP sont limitées au streaming half-duplex uniquement.

Par défaut, les méthodes de streaming bidirectionnel dans les APIs Cloud supposent la sémantique full-duplex. Autrement dit, il n'est pas sûr d'utiliser HTTP pour appeler une telle méthode. Si une méthode de streaming est uniquement half-duplex (comme appliqué par le serveur), le document de l'API doit spécifier clairement le comportement half-duplex.

Pour les clients de navigateur, la sémantique HTTP standard est davantage limitée par les API réseau des navigateurs. Les navigateurs sont compatibles avec le streaming serveur (qui respecte généralement le framing au niveau du transport) à l'aide de XHR ou de Fetch. L'API Fetch utilise des flux whatwg.

En raison des restrictions du navigateur, les APIs Cloud qui nécessitent la compatibilité avec le navigateur doivent éviter le streaming client ainsi que le streaming full-duplex, ou fournir une API distincte spécifiquement pour les clients de navigateur.

En règle générale, le streaming client sur Internet est moins utile que le streaming serveur. En effet, l'utilisation du streaming client conduit souvent à un service avec état, ce qui nuit à l'équilibrage de charge et rend le système plus vulnérable aux défaillances ou aux attaques. Le streaming serveur, en revanche, peut être utile, car il peut réduire considérablement la latence sur les réseaux avec de longs délais DAR.

Encodage de messages

Les messages JSON lors de la transmission en continu sont encodés sous la forme d'un tableau de messages JSON. Le corps de la requête ou de la réponse restera sous la forme d'un type MIME JSON valide.

Exemple d'encodage de flux de client :

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

Exemple d'encodage de flux de serveur :

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

Encodage au niveau de la communication : la définition de StreamBody n'est significative que dans son allocation d'ID de tag pour les champs "messages" et "status" <length> qui seront encodés en varint avec 1 à 2 octets pour les messages normaux. La surcharge d'encodage totale est donc de 2 à 3 octets par message.

Un champ de remplissage facultatif est nécessaire pour prendre en charge les flux encodés en base64 :

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

Les messages d'erreur doivent être ajoutés en tant que dernier élément du tableau JSON ou protobuf, dans le même format que les messages habituels.

Gestion de l'état

Le comportement de fermeture partielle est bien défini dans toute version HTTP pour un client ou un serveur afin de signaler à l'autre extrémité que le corps est terminé.

En particulier, le code client est libre de terminer la requête alors que la réponse est en attente. De même, un client peut voir une réponse complète lorsque le corps de la requête est toujours en cours d'écriture sur le serveur. La norme HTTP s'attend à ce que le client abandonne ou termine la requête lorsqu'une réponse s'est terminée de manière inattendue, généralement associée à un état d'erreur. En d'autres termes, dans des conditions normales, le serveur ne doit pas terminer une réponse lorsque le client envoie toujours la requête.

Annulation

L'annulation permet à un client d'abandonner une requête alors que la requête ou la réponse est toujours en cours.

Il n'existe pas de compatibilité fiable avec l'annulation pour les clients HTTP/1.*, car un client est libre de fermer une connexion TCP une fois la requête terminée sans abandonner la transaction de requête ou de réponse. Un TCP FIN, sous HTTP/1.1, ne doit pas être interprété comme une annulation, même lorsque la connexion est marquée comme une connexion keep-alive (Connection: Keep-Alive).

Toutefois, après la fermeture de la connexion TCP par le client, si le serveur tente d'écrire des données sur le client, un fichier RST est généré, ce qui peut déclencher une annulation.

Notez également que l'annulation est également un problème pour les API en flux non continu. C'est particulièrement le cas lorsque la réponse implique un long polling et que la connexion peut donc rester inactive pendant une période prolongée.

L'annulation explicite est compatible avec SPDY, HTTP/2 et QUIC, en particulier avec le message de départ.

Message keep-alive

Le message keep-alive permet à un client ou à un serveur de détecter un pair défaillant, même en cas de perte de paquets ou de défaillance du réseau.

HTTP/1.1 n'est pas compatible avec la fonctionnalité keep-alive, car les messages keep-alive de TCP ne représentent pas une approche viable.

QUIC ou HTTP/2 proposent des messages de contrôle spéciaux afin d'implémenter la compatibilité avec les messages keep-alive par les applications, y compris les navigateurs.

Cependant, une détection fiable des échecs et des messages keep-alive nécessitera probablement une bibliothèque cliente avec la compatibilité nécessaire côté serveur. La diffusion longue durée en continu sur Internet est souvent sujette aux erreurs lorsque le protocole HTTP de base est utilisé.

Contrôle de flux

La compatibilité avec le contrôle de flux nécessite que le client propage les événements de contrôle de flux au niveau du transport à l'application cliente. Le mécanisme réel dépend du style de l'API cliente HTTP utilisée par votre application cliente. Par exemple, vous avez besoin d'écritures et de lectures bloquantes, ou de lectures et d'écritures non bloquantes avec une compatibilité explicite avec le contrôle de flux pour que les applications gèrent et respectent les événements de contrôle de flux, afin d'éviter que le client ou le serveur ne soient surchargés.

HTTP/1.1 repose sur le contrôle de flux TCP.

SPDY et HTTP/2 ont leur propre contrôle de flux au niveau du flux, qui est également soumis au contrôle de flux TCP au niveau de la connexion, car les requêtes sont multiplexées sur une seule connexion TCP.

QUIC s'exécute sur UDP et gère donc le contrôle de flux de manière entièrement autonome.