Consignes sur HTTP

Ce document décrit le fonctionnement des API Google avec différentes versions et mises en œuvre HTTP. Si vous utilisez l'une de nos bibliothèques clientes générées ou créées à la main (approche que nous recommandons dans la plupart des cas d'utilisation), vous n'avez pas à vous inquiéter, car le code fourni traite des problèmes de bas niveau liés à la communication avec le serveur.

Toutefois, si vous êtes un développeur expérimenté et que vous avez besoin d'écrire votre propre code personnalisé pour accéder directement à l'interface REST d'une API à l'aide d'une bibliothèque cliente HTTP tierce de votre choix, vous devez comprendre au moins certaines des sémantiques documentées ici (pertinentes pour votre API choisie) et prendre connaissance de ce qui est fourni par votre bibliothèque HTTP.

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 Cloud peuvent utiliser pour communiquer entre clients et serveurs, ainsi que la façon dont nous vous recommandons de les utiliser. Nous verrons les détails de la structure des requêtes et des réponses dans la section ci-dessous.

Sémantique HTTP

Lors du développement du code client de l'API, respectez la sémantique du protocole HTTP standard. Les serveurs proxy côté serveur ou les piles d'API sont exclusivement compatibles avec un sous-ensemble de fonctionnalités HTTP standards et leurs versions rétrocompatibles.

La sémantique du protocole HTTP qui doit être gérée par les mises en œuvre des API côté serveur 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 les protocoles HTTP/* autorisés par la plate-forme cliente ou leur réseau côté client, ou négociés avec le proxy côté serveur. Les protocoles possibles sont HTTP/1.0, HTTP/1.1, SPDY/*, HTTP/2 et QUIC.

Certaines fonctionnalités de l'API peuvent n'être compatibles qu'avec les versions les plus récentes des protocoles HTTP, telles que l'envoi de serveur et les priorités. D'autres ne sont entièrement spécifiées qu'avec HTTP/2, telles que la diffusion en duplex intégral. Tenez compte des limitations 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.

En règle générale, nous recommandons HTTP/2 pour de meilleures performances et une résilience aux pannes de réseau.

Canaux

Les canaux font référence aux connexions réseau L4 (sockets TCP ou UDP). Les applications clientes ne doivent faire aucune hypothèse sur la manière dont les canaux sont utilisés au moment de l'exécution pour traiter les requêtes HTTP. Dans presque tous les cas, les canaux sont terminés par des serveurs proxy pour le compte du processus serveur.

Pour les clients HTTP/1.1, réutilisez toujours les connexions TCP (Connexion : Keep-Alive). La bibliothèque cliente HTTP gérera probablement aussi un pool de connexions pour de meilleures performances. Ne concentrez pas les requêtes sur la même connexion TCP. Consultez la section HTTP et TCP pour plus d'informations.

Les navigateurs modernes connaissent tous SPDY/*, HTTP/2 ou QUIC, qui multiplexent les requêtes sur un seul canal. La limite de connexion traditionnelle (2-10) ne devrait jamais être un problème, sauf lorsque la mise en œuvre du serveur limite le nombre de requêtes HTTP simultanées provenant d'un seul client, par exemple 100 flux HTTP/2 pour une seule origine.

HTTPS

Les clients peuvent accéder à une API via HTTPS ou HTTP, conformément aux 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/réponse

URL de requête

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

Le corps HTTP utilise un tableau JSON pour traiter les méthodes RPC diffusées en continu. Le tableau JSON peut contenir un nombre quelconque de messages JSON ou un message JSON avec un état d'erreur.

URL de requête longues

L'URL a une limite de longueur pratique, généralement entre 2 000 et 8 000. Elle est appliquée par certains navigateurs et serveurs proxy. Si votre API utilise des requêtes GET avec des URL dépassant la limite de longueur, ces requêtes peuvent être rejetées par les navigateurs. Pour contourner la limitation, le code client doit utiliser une requête POST avec application/x-www-form-urlencoded comme type de contenu et X-HTTP-Method-Override: GET comme en-tête HTTP. 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 API doit être conforme aux exigences du protocole HTTP basé sur le verbe HTTP spécifique auquel la méthode API est mappée. Pour plus de détails, reportez-vous à la spécification du protocole HTTP (Hypertext Transfer Protocol) et au 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 doivent 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

  • Les requêtes et les réponses doivent partager le même type de contenu, sauf si la requête est de type 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. La valeur Content-Type acceptée est application/x-www-form-urlencoded.

Streaming

Semi-duplex contre duplex intégral

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 utiliser le corps de la réponse en mode de diffusion en continu, c'est-à-dire en diffusion en continu sur le serveur.

Cependant, la spécification HTTP n'indique pas si un serveur est autorisé à retransmettre le corps de la réponse (sauf pour les réponses d'erreur) lorsque le corps de la requête est toujours en cours. Cette sémantique est connue sous le nom de diffusion en duplex intégral. Bien que de nombreux logiciels client/serveur/proxy HTTP autorisent la diffusion duplex intégral, 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 à la diffusion en semi-duplex.

Par défaut, les méthodes de diffusion bidid dans les API Cloud utilisent la sémantique de diffusion en duplex intégral. Autrement dit, il n'est pas sûr d'utiliser HTTP pour appeler une telle méthode. Si une méthode de diffusion est exclusivement en mode semi-duplex (tel qu'imposé par le serveur), le document de l'API doit spécifier clairement le comportement de ce mode.

Pour les clients de navigateur, la sémantique HTTP standard est davantage limitée par les API réseau des navigateurs. Actuellement, les navigateurs ne sont compatibles qu'avec la diffusion sur serveur (qui respecte généralement l'encadrement au niveau du transport) via XHR ou Fetch. L'API Fetch utilise les flux Whatwg.

En raison de restrictions liées aux navigateurs, les API Cloud nécessitant une compatibilité avec les navigateurs doivent éviter la diffusion sur client et la diffusion en duplex intégral. Sinon, elles doivent fournir une API distincte spécifiquement pour les clients de navigateur.

De manière générale, la diffusion en continu sur le client est moins utile sur Internet que la diffusion en continu sur le serveur. Cela s'explique par le fait que l'utilisation de la diffusion en continu sur le client conduit souvent à un service associé à un état, ce qui nuit à l'équilibrage de la charge et rend le système plus vulnérable aux pannes et aux attaques. La diffusion sur serveur, en revanche, peut être utile, car elle peut réduire considérablement la latence sur les réseaux présentant de longs délais RTT.

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

Codage au niveau de la communication : la définition de "StreamBody" n’est significative que si elle attribue des identifiants de balises pour le champ "messages" et "état" sera encodé avec un entier variable compris entre 1 à 2 octets pour les messages normaux, de sorte que la surcharge totale d'encodage ne dépassera pas 2 à 3 octets par message.

Un champ de marge intérieure facultatif est nécessaire pour accepter 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 terminée lorsque le corps de la requête est encore 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. Cela signifie que, dans des conditions normales, le serveur ne doit pas répondre avant que le client ne renvoie 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 d’annulation fiable pour les clients HTTP/1.*, puisqu'un client est libre de fermer une connexion TCP une fois la requête terminée sans abandonner la transaction requête/réponse. Un message "TCP FIN" sous HTTP/1.1 ne doit pas être interprété comme une annulation, même lorsque la connexion est associée à un message keep-alive (Connexion : 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. Cela est particulièrement le cas lorsque la réponse implique une longue interrogation et que, par conséquent, la connexion peut 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 offrent des messages de contrôle spéciaux destinés à mettre en œuvre la compatibilité avec keep-alive sur 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

Le contrôle de flux nécessite que le client propage les événements de contrôle de flux au niveau du transport vers 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 écritures non bloquantes avec un contrôle de flux explicite pour que les applications gèrent et respectent les événements de contrôle de flux, afin d'éviter toute surcharge du client ou du serveur.

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, les requêtes étant multiplexées sur une seule connexion TCP.

QUIC s'exécute sur UDP et gère donc lui-même le contrôle de flux.