5. Streams and Multiplexing (Flux et Multiplexage)
Un « flux (stream) » est une séquence indépendante et bidirectionnelle de trames échangées entre le client et le serveur au sein d'une connexion HTTP/2. Les flux ont plusieurs caractéristiques importantes :
-
Une seule connexion HTTP/2 peut contenir plusieurs flux ouverts simultanément, chaque extrémité entrelaçant les trames de plusieurs flux.
-
Les flux peuvent être établis et utilisés unilatéralement ou partagés par le client ou le serveur.
-
Les flux peuvent être fermés par l'une ou l'autre extrémité.
-
L'ordre dans lequel les trames sont envoyées sur un flux est significatif. Les destinataires traitent les trames dans l'ordre où elles sont reçues. En particulier, l'ordre des trames HEADERS et DATA est sémantiquement significatif.
-
Les flux sont identifiés par un entier. Les identifiants de flux sont attribués aux flux par l'extrémité qui initie le flux.
5.1. Stream States (États des Flux)
Le cycle de vie d'un flux est illustré dans la figure 2.
+--------+
send PP | | recv PP
,--------+ idle +--------.
/ | | \
v +--------+ v
+----------+ | +----------+
| | | send H / | |
,-----+ reserved | | recv H | reserved +-----.
| | (local) | | | (remote) | |
| +---+------+ v +------+---+ |
| | +--------+ | |
| | recv ES | | send ES | |
| send H | ,-------+ open +-------. | recv H |
| | / | | \ | |
| v v +---+----+ v v |
| +----------+ | +----------+ |
| | half- | | | half- | |
| | closed | | send R / | closed | |
| | (remote) | | recv R | (local) | |
| +----+-----+ | +-----+----+ |
| | | | |
| | send ES / | recv ES / | |
| | send R / v send R / | |
| | recv R +--------+ recv R | |
| send R / `----------->| |<-----------' send R / |
| recv R | closed | recv R |
`----------------------->| |<----------------------'
+--------+
send: l'extrémité envoie cette trame
recv: l'extrémité reçoit cette trame
H: trame HEADERS (avec trames CONTINUATION implicites)
PP: trame PUSH_PROMISE (avec trames CONTINUATION implicites)
ES: drapeau END_STREAM
R: trame RST_STREAM
Figure 2 : États des Flux
Notez que ce diagramme ne montre que les transitions d'état de flux et les trames et drapeaux qui affectent ces changements d'état. À cet égard, les trames CONTINUATION n'entraînent pas de transitions d'état et font effectivement partie des HEADERS ou PUSH_PROMISE qu'elles suivent. Aux fins des transitions d'état, le drapeau END_STREAM est traité comme un événement distinct de la trame qui le porte ; une trame HEADERS avec le drapeau END_STREAM défini peut provoquer deux transitions d'état.
Les deux extrémités ont une vue subjective de l'état d'un flux qui pourrait être différente lorsque les trames sont en transit. Les extrémités ne coordonnent pas la création de flux ; ils sont créés unilatéralement par l'une ou l'autre extrémité. Les conséquences négatives d'une discordance d'états sont limitées à l'état « closed » après l'envoi de RST_STREAM, où des trames peuvent être reçues pendant un certain temps après la fermeture.
Les flux ont les états suivants :
idle (inactif) : Tous les flux commencent dans l'état « idle ».
Les transitions suivantes sont valides à partir de cet état :
-
L'envoi ou la réception d'une trame HEADERS fait passer le flux à l'état « open ». L'identifiant de flux est sélectionné comme décrit dans la section 5.1.1. La même trame HEADERS peut également faire passer immédiatement un flux à l'état « half-closed ».
-
L'envoi d'une trame PUSH_PROMISE sur un autre flux réserve le flux inactif identifié pour une utilisation ultérieure. L'état du flux pour le flux réservé passe à « reserved (local) ».
-
La réception d'une trame PUSH_PROMISE sur un autre flux réserve un flux inactif identifié pour une utilisation ultérieure. L'état du flux pour le flux réservé passe à « reserved (remote) ».
-
Notez que la trame PUSH_PROMISE n'est pas envoyée sur le flux inactif mais référence le flux nouvellement réservé dans le champ Promised Stream ID.
La réception de toute trame autre que HEADERS ou PRIORITY sur un flux dans cet état DOIT être traitée comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
reserved (local) (réservé (local)) : Un flux dans l'état « reserved (local) » est un flux qui a été promis en envoyant une trame PUSH_PROMISE. Une trame PUSH_PROMISE réserve un flux inactif en associant le flux à un flux ouvert qui a été initié par le pair distant (voir Section 8.4).
Dans cet état, seules les transitions suivantes sont possibles :
-
L'extrémité peut envoyer une trame HEADERS. Cela fait passer le flux à l'état « half-closed (remote) ».
-
L'une ou l'autre extrémité peut envoyer une trame RST_STREAM pour faire passer le flux à l'état « closed ». Cela libère la réservation de flux.
Une extrémité NE DOIT PAS envoyer de trame d'un type autre que HEADERS, RST_STREAM ou PRIORITY dans cet état.
Une trame PRIORITY ou WINDOW_UPDATE PEUT être reçue dans cet état. La réception de tout type de trame autre que RST_STREAM, PRIORITY ou WINDOW_UPDATE sur un flux dans cet état DOIT être traitée comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
reserved (remote) (réservé (distant)) : Un flux dans l'état « reserved (remote) » a été réservé par un pair distant.
Dans cet état, seules les transitions suivantes sont possibles :
-
La réception d'une trame HEADERS fait passer le flux à l'état « half-closed (local) ».
-
L'une ou l'autre extrémité peut envoyer une trame RST_STREAM pour faire passer le flux à l'état « closed ». Cela libère la réservation de flux.
Une extrémité PEUT envoyer une trame PRIORITY dans cet état pour reprioriser le flux réservé. Une extrémité NE DOIT PAS envoyer de trame d'un type autre que RST_STREAM, WINDOW_UPDATE ou PRIORITY dans cet état.
La réception de tout type de trame autre que HEADERS, RST_STREAM ou PRIORITY sur un flux dans cet état DOIT être traitée comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
open (ouvert) : Un flux dans l'état « open » peut être utilisé par les deux pairs pour envoyer des trames de tout type. Dans cet état, les pairs émetteurs observent les limites de contrôle de flux au niveau du flux annoncées (Section 5.2).
À partir de cet état, l'une ou l'autre extrémité peut envoyer une trame avec le drapeau END_STREAM défini, ce qui fait passer le flux dans l'un des états « half-closed ». Une extrémité envoyant un drapeau END_STREAM fait passer l'état du flux à « half-closed (local) » ; une extrémité recevant un drapeau END_STREAM fait passer l'état du flux à « half-closed (remote) ».
L'une ou l'autre extrémité peut envoyer une trame RST_STREAM à partir de cet état, la faisant passer immédiatement à l'état « closed ».
half-closed (local) (semi-fermé (local)) : Un flux dans l'état « half-closed (local) » ne peut pas être utilisé pour envoyer des trames autres que WINDOW_UPDATE, PRIORITY et RST_STREAM.
Un flux passe de cet état à « closed » lorsqu'une trame est reçue avec le drapeau END_STREAM défini ou lorsque l'un des pairs envoie une trame RST_STREAM.
Une extrémité peut recevoir tout type de trame dans cet état. Fournir un crédit de contrôle de flux à l'aide de trames WINDOW_UPDATE est nécessaire pour continuer à recevoir des trames contrôlées par flux. Dans cet état, un récepteur peut ignorer les trames WINDOW_UPDATE, qui peuvent arriver pendant une courte période après l'envoi d'une trame avec le drapeau END_STREAM défini.
Les trames PRIORITY reçues dans cet état sont utilisées pour reprioriser les flux qui dépendent du flux identifié.
half-closed (remote) (semi-fermé (distant)) : Un flux « half-closed (remote) » n'est plus utilisé par le pair pour envoyer des trames. Dans cet état, une extrémité n'est plus obligée de maintenir une fenêtre de contrôle de flux du récepteur.
Si une extrémité reçoit des trames supplémentaires, autres que WINDOW_UPDATE, PRIORITY ou RST_STREAM, pour un flux dans cet état, elle DOIT répondre avec une erreur de flux (Section 5.4.2) de type STREAM_CLOSED.
Un flux « half-closed (remote) » peut être utilisé par l'extrémité pour envoyer des trames de tout type. Dans cet état, l'extrémité continue d'observer les limites de contrôle de flux au niveau du flux annoncées (Section 5.2).
Un flux peut passer de cet état à « closed » en envoyant une trame avec le drapeau END_STREAM défini ou lorsque l'un des pairs envoie une trame RST_STREAM.
closed (fermé) : L'état « closed » est l'état terminal.
Une extrémité NE DOIT PAS envoyer de trames autres que PRIORITY sur un flux fermé. Une extrémité qui reçoit une trame autre que PRIORITY après avoir reçu un RST_STREAM DOIT traiter cela comme une erreur de flux (Section 5.4.2) de type STREAM_CLOSED. De même, une extrémité qui reçoit des trames après avoir reçu une trame avec le drapeau END_STREAM défini DOIT traiter cela comme une erreur de connexion (Section 5.4.1) de type STREAM_CLOSED, sauf si la trame est autorisée comme décrit ci-dessous.
Des trames WINDOW_UPDATE ou RST_STREAM peuvent être reçues dans cet état pendant une courte période après l'envoi d'une trame DATA ou HEADERS contenant un drapeau END_STREAM. Jusqu'à ce que le pair distant reçoive et traite RST_STREAM ou la trame portant le drapeau END_STREAM, il peut envoyer des trames de ces types. Les extrémités DOIVENT ignorer les trames WINDOW_UPDATE ou RST_STREAM reçues dans cet état, bien que les extrémités PUISSENT choisir de traiter les trames qui arrivent un temps significatif après l'envoi d'END_STREAM comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
Les trames PRIORITY peuvent être envoyées sur des flux fermés pour prioriser les flux qui dépendent du flux fermé. Les extrémités DEVRAIENT traiter les trames PRIORITY, bien qu'elles puissent être ignorées si le flux a été supprimé de l'arbre de dépendance (voir Section 5.3.3 de [RFC7540]).
Si cet état est atteint suite à l'envoi d'une trame RST_STREAM, le pair qui reçoit le RST_STREAM peut avoir déjà envoyé -- ou mis en file d'attente pour l'envoi -- des trames sur le flux qui ne peuvent pas être retirées. Une extrémité DOIT ignorer les trames qu'elle reçoit sur des flux fermés après avoir envoyé une trame RST_STREAM. Une extrémité PEUT choisir de limiter la période pendant laquelle elle ignore les trames et de traiter les trames qui arrivent après cette période comme étant en erreur.
Les trames contrôlées par flux (c'est-à-dire DATA) reçues après l'envoi de RST_STREAM sont comptabilisées dans la fenêtre de contrôle de flux de la connexion. Même si ces trames peuvent être ignorées, parce qu'elles sont envoyées avant que l'émetteur ne reçoive le RST_STREAM, l'émetteur considérera que les trames comptent par rapport à la fenêtre de contrôle de flux.
Une extrémité peut recevoir une trame PUSH_PROMISE après avoir envoyé RST_STREAM. PUSH_PROMISE fait passer un flux à l'état « reserved » même si le flux associé a été réinitialisé. Par conséquent, un RST_STREAM est nécessaire pour fermer un flux promis non désiré.
En l'absence de règles plus spécifiques, les implémentations DEVRAIENT traiter la réception d'une trame qui n'est pas expressément autorisée dans la description d'un état comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR. Notez que PRIORITY peut être envoyé et reçu dans n'importe quel état de flux.
Les règles de cette section ne s'appliquent qu'aux trames définies dans ce document. La réception de trames dont la sémantique est inconnue ne peut pas être traitée comme une erreur, car les conditions d'envoi et de réception de ces trames sont également inconnues ; voir Section 5.5.
Un exemple des transitions d'état pour un échange de requête/réponse HTTP peut être trouvé dans la Section 8.8. Un exemple des transitions d'état pour le push serveur peut être trouvé dans les Sections 8.4.1 et 8.4.2.
5.1.1. Stream Identifiers (Identifiants de Flux)
Les flux sont identifiés par un entier non signé de 31 bits. Les flux initiés par un client DOIVENT utiliser des identifiants de flux impairs ; ceux initiés par le serveur DOIVENT utiliser des identifiants de flux pairs. Un identifiant de flux de zéro (0x00) est utilisé pour les messages de contrôle de connexion ; l'identifiant de flux zéro ne peut pas être utilisé pour établir un nouveau flux.
L'identifiant d'un flux nouvellement établi DOIT être numériquement supérieur à tous les flux que l'extrémité initiatrice a ouverts ou réservés. Ceci régit les flux qui sont ouverts à l'aide d'une trame HEADERS et les flux qui sont réservés à l'aide de PUSH_PROMISE. Une extrémité qui reçoit un identifiant de flux inattendu DOIT répondre avec une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
Une trame HEADERS fera passer le flux initié par le client identifié par l'identifiant de flux dans l'en-tête de trame de « idle » à « open ». Une trame PUSH_PROMISE fera passer le flux initié par le serveur identifié par le champ Promised Stream ID dans la charge utile de trame de « idle » à « reserved (local) » ou « reserved (remote) ». Lorsqu'un flux sort de l'état « idle », tous les flux dans l'état « idle » qui auraient pu être ouverts par le pair avec un identifiant de flux de valeur inférieure passent immédiatement à l'état « closed ». Autrement dit, une extrémité peut sauter un identifiant de flux, l'effet étant que le flux sauté est immédiatement fermé.
Les identifiants de flux ne peuvent pas être réutilisés. Les connexions de longue durée peuvent entraîner l'épuisement de la plage disponible d'identifiants de flux par une extrémité. Un client qui ne peut pas établir un nouvel identifiant de flux peut établir une nouvelle connexion pour de nouveaux flux. Un serveur qui ne peut pas établir un nouvel identifiant de flux peut envoyer une trame GOAWAY afin que le client soit forcé d'ouvrir une nouvelle connexion pour de nouveaux flux.
5.1.2. Stream Concurrency (Concurrence de Flux)
Un pair peut limiter le nombre de flux actifs simultanément en utilisant le paramètre SETTINGS_MAX_CONCURRENT_STREAMS (voir Section 6.5.2) dans une trame SETTINGS. Le paramètre de flux concurrents maximum est spécifique à chaque extrémité et s'applique uniquement au pair qui reçoit le paramètre. Autrement dit, les clients spécifient le nombre maximum de flux concurrents que le serveur peut initier, et les serveurs spécifient le nombre maximum de flux concurrents que le client peut initier.
Les flux qui sont dans l'état « open » ou dans l'un des états « half-closed » comptent pour le nombre maximum de flux qu'une extrémité est autorisée à ouvrir. Les flux dans l'un de ces trois états comptent pour la limite annoncée dans le paramètre SETTINGS_MAX_CONCURRENT_STREAMS. Les flux dans l'un des états « reserved » ne comptent pas pour la limite de flux.
Les extrémités NE DOIVENT PAS dépasser la limite fixée par leur pair. Une extrémité qui reçoit une trame HEADERS qui entraîne le dépassement de sa limite de flux concurrents annoncée DOIT traiter cela comme une erreur de flux (Section 5.4.2) de type PROTOCOL_ERROR ou REFUSED_STREAM. Le choix du code d'erreur détermine si l'extrémité souhaite activer la nouvelle tentative automatique (voir Section 8.7 pour plus de détails).
Une extrémité qui souhaite réduire la valeur de SETTINGS_MAX_CONCURRENT_STREAMS à une valeur inférieure au nombre actuel de flux ouverts peut soit fermer les flux qui dépassent la nouvelle valeur, soit autoriser les flux à se terminer.
5.2. Flow Control (Contrôle de Flux)
L'utilisation de flux pour le multiplexage introduit une contention sur l'utilisation de la connexion TCP, ce qui entraîne le blocage des flux. Un schéma de contrôle de flux garantit que les flux sur la même connexion n'interfèrent pas de manière destructive les uns avec les autres. Le contrôle de flux est utilisé à la fois pour les flux individuels et pour la connexion dans son ensemble.
HTTP/2 fournit un contrôle de flux grâce à l'utilisation de la trame WINDOW_UPDATE (Section 6.9).
5.2.1. Flow-Control Principles (Principes du Contrôle de Flux)
Le contrôle de flux de flux HTTP/2 vise à permettre l'utilisation d'une variété d'algorithmes de contrôle de flux sans nécessiter de modifications du protocole. Le contrôle de flux dans HTTP/2 présente les caractéristiques suivantes :
-
Le contrôle de flux est spécifique à une connexion. Le contrôle de flux HTTP/2 fonctionne entre les extrémités d'un seul saut et non sur l'ensemble du chemin de bout en bout.
-
Le contrôle de flux est basé sur des trames WINDOW_UPDATE. Les récepteurs annoncent combien d'octets ils sont prêts à recevoir sur un flux et pour l'ensemble de la connexion. Il s'agit d'un schéma basé sur le crédit.
-
Le contrôle de flux est directionnel avec un contrôle global fourni par le récepteur. Un récepteur PEUT choisir de définir la taille de fenêtre qu'il souhaite pour chaque flux et pour l'ensemble de la connexion. Un émetteur DOIT respecter les limites de contrôle de flux imposées par un récepteur. Les clients, serveurs et intermédiaires annoncent tous indépendamment leur fenêtre de contrôle de flux en tant que récepteur et respectent les limites de contrôle de flux définies par leur pair lors de l'envoi.
-
La valeur initiale de la fenêtre de contrôle de flux est de 65 535 octets pour les nouveaux flux et pour l'ensemble de la connexion.
-
Le type de trame détermine si le contrôle de flux s'applique à une trame. Parmi les trames spécifiées dans ce document, seules les trames DATA sont soumises au contrôle de flux ; tous les autres types de trames ne consomment pas d'espace dans la fenêtre de contrôle de flux annoncée. Cela garantit que les trames de contrôle importantes ne sont pas bloquées par le contrôle de flux.
-
Une extrémité peut choisir de désactiver son propre contrôle de flux, mais une extrémité ne peut pas ignorer les signaux de contrôle de flux de son pair.
-
HTTP/2 définit uniquement le format et la sémantique de la trame WINDOW_UPDATE (Section 6.9). Ce document ne stipule pas comment un récepteur décide quand envoyer cette trame ou la valeur qu'il envoie, ni ne spécifie comment un émetteur choisit d'envoyer des paquets. Les implémentations peuvent sélectionner tout algorithme qui convient à leurs besoins.
Les implémentations sont également responsables de la priorisation de l'envoi des requêtes et des réponses, du choix de la manière d'éviter le blocage de tête de ligne pour les requêtes et de la gestion de la création de nouveaux flux. Les choix d'algorithmes pour ceux-ci pourraient interagir avec n'importe quel algorithme de contrôle de flux.
5.2.2. Appropriate Use of Flow Control (Utilisation Appropriée du Contrôle de Flux)
Le contrôle de flux est défini pour protéger les extrémités qui fonctionnent sous des contraintes de ressources. Par exemple, un proxy doit partager la mémoire entre de nombreuses connexions et peut également avoir une connexion en amont lente et une connexion en aval rapide. Le contrôle de flux traite les cas où le récepteur est incapable de traiter les données sur un flux mais souhaite continuer à traiter d'autres flux sur la même connexion.
Les déploiements qui ne nécessitent pas cette capacité peuvent annoncer une fenêtre de contrôle de flux de la taille maximale (2^31-1) et peuvent maintenir cette fenêtre en envoyant une trame WINDOW_UPDATE lorsque des données sont reçues. Cela désactive effectivement le contrôle de flux pour ce récepteur. Inversement, un émetteur est toujours soumis à la fenêtre de contrôle de flux annoncée par le récepteur.
Les déploiements avec des ressources limitées (par exemple, la mémoire) peuvent utiliser le contrôle de flux pour limiter la quantité de mémoire qu'un pair peut consommer. Notez cependant que cela peut conduire à une utilisation sous-optimale des ressources réseau disponibles si le contrôle de flux est activé sans connaissance du produit bande passante × délai (voir [RFC7323]).
Même avec une connaissance complète du produit bande passante × délai actuel, la mise en œuvre du contrôle de flux peut être difficile. Les extrémités DOIVENT lire et traiter les trames HTTP/2 du tampon de réception TCP dès que les données sont disponibles. Ne pas lire rapidement pourrait conduire à une impasse lorsque des trames critiques, telles que WINDOW_UPDATE, ne sont pas lues et traitées. La lecture rapide des trames n'expose pas les extrémités aux attaques d'épuisement des ressources, car le contrôle de flux HTTP/2 limite les engagements de ressources.
5.2.3. Flow-Control Performance (Performance du Contrôle de Flux)
Si une extrémité ne peut pas garantir que son pair dispose toujours d'un espace de fenêtre de contrôle de flux disponible supérieur au produit bande passante × délai du pair sur cette connexion, son débit de réception sera limité par le contrôle de flux HTTP/2. Cela entraînera une dégradation des performances.
L'envoi de trames WINDOW_UPDATE en temps opportun peut améliorer les performances. Les extrémités voudront équilibrer le besoin d'améliorer le débit de réception avec le besoin de gérer les risques d'épuisement des ressources et devront prendre note attentivement de la Section 10.5 lors de la définition de leur stratégie de gestion des tailles de fenêtre.
5.3. Prioritization (Priorisation)
Dans un protocole multiplexé comme HTTP/2, la priorisation de l'allocation de la bande passante et des ressources de calcul aux flux peut être essentielle pour obtenir de bonnes performances. Un mauvais schéma de priorisation peut entraîner HTTP/2 à fournir de mauvaises performances. Sans parallélisme au niveau de la couche TCP, les performances pourraient être significativement pires que HTTP/1.1.
Un bon schéma de priorisation bénéficie de l'application de connaissances contextuelles telles que le contenu des ressources, la manière dont les ressources sont interdépendantes et la manière dont ces ressources seront utilisées par un pair. En particulier, les clients peuvent posséder des connaissances sur la priorité des requêtes qui sont pertinentes pour la priorisation du serveur. Dans ces cas, faire en sorte que les clients fournissent des informations de priorité peut améliorer les performances.
5.3.1. Background on Priority in RFC 7540 (Contexte de la Priorité dans RFC 7540)
RFC 7540 a défini un système riche pour signaler la priorité des requêtes. Cependant, ce système s'est avéré complexe et n'a pas été implémenté de manière uniforme.
Le schéma flexible signifiait qu'il était possible pour les clients d'exprimer les priorités de manières très différentes, avec peu de cohérence dans les approches adoptées. Pour les serveurs, la mise en œuvre d'un support générique pour le schéma était complexe. La mise en œuvre des priorités était inégale dans les clients et les serveurs. De nombreux déploiements de serveurs ignoraient les signaux des clients lors de la priorisation de leur traitement des requêtes.
En bref, la signalisation de priorisation dans RFC 7540 [RFC7540] n'a pas réussi.
5.3.2. Priority Signaling in This Document (Signalisation de Priorité dans ce Document)
Cette mise à jour d'HTTP/2 déprécie la signalisation de priorité définie dans RFC 7540 [RFC7540]. La majeure partie du texte relatif aux signaux de priorité n'est pas incluse dans ce document. La description des champs de trame et une partie du traitement obligatoire sont conservées pour garantir que les implémentations de ce document restent interopérables avec les implémentations qui utilisent la signalisation de priorité décrite dans RFC 7540.
Une description complète du schéma de priorité RFC 7540 reste dans la Section 5.3 de [RFC7540].
La signalisation d'informations de priorité est nécessaire pour obtenir de bonnes performances dans de nombreux cas. Lorsque la signalisation d'informations de priorité est importante, les extrémités sont encouragées à utiliser un schéma alternatif, tel que le schéma décrit dans [HTTP-PRIORITY].
Bien que la signalisation de priorité de RFC 7540 n'ait pas été largement adoptée, les informations qu'elle fournit peuvent toujours être utiles en l'absence de meilleures informations. Les extrémités qui reçoivent des signaux de priorité dans les trames HEADERS ou PRIORITY peuvent bénéficier de l'application de ces informations. En particulier, les implémentations qui consomment ces signaux ne bénéficieraient pas de l'abandon de ces signaux de priorité en l'absence d'alternatives.
Les serveurs DEVRAIENT utiliser d'autres informations contextuelles pour déterminer la priorité des requêtes en l'absence de signaux de priorité. Les serveurs PEUVENT interpréter l'absence complète de signaux comme une indication que le client n'a pas implémenté la fonctionnalité. Les valeurs par défaut décrites dans la Section 5.3.5 de [RFC7540] sont connues pour avoir de mauvaises performances dans la plupart des conditions, et leur utilisation est peu susceptible d'être délibérée.
5.4. Error Handling (Gestion des Erreurs)
Le cadrage HTTP/2 permet deux classes d'erreurs :
-
Une condition d'erreur qui rend l'ensemble de la connexion inutilisable est une erreur de connexion (connection error).
-
Une erreur dans un flux individuel est une erreur de flux (stream error).
Une liste de codes d'erreur est incluse dans la Section 7.
Il est possible qu'une extrémité rencontre des trames qui provoqueraient plusieurs erreurs. Les implémentations PEUVENT découvrir plusieurs erreurs pendant le traitement, mais elles DEVRAIENT signaler au plus une erreur de flux et une erreur de connexion en conséquence.
La première erreur de flux signalée pour un flux donné empêche toute autre erreur sur ce flux d'être signalée. En comparaison, le protocole permet plusieurs trames GOAWAY, bien qu'une extrémité DEVRAIT signaler un seul type d'erreur de connexion à moins qu'une erreur ne soit rencontrée pendant l'arrêt gracieux. Si cela se produit, une extrémité PEUT envoyer une trame GOAWAY supplémentaire avec le nouveau code d'erreur, en plus de tout GOAWAY antérieur qui contenait NO_ERROR.
Si une extrémité détecte plusieurs erreurs différentes, elle PEUT choisir de signaler l'une de ces erreurs. Si une trame provoque une erreur de connexion, cette erreur DOIT être signalée. De plus, une extrémité PEUT utiliser tout code d'erreur applicable lorsqu'elle détecte une condition d'erreur ; un code d'erreur générique (tel que PROTOCOL_ERROR ou INTERNAL_ERROR) peut toujours être utilisé à la place de codes d'erreur plus spécifiques.
5.4.1. Connection Error Handling (Gestion des Erreurs de Connexion)
Une erreur de connexion est toute erreur qui empêche le traitement ultérieur de la couche de trame ou corrompt tout état de connexion.
Une extrémité qui rencontre une erreur de connexion DEVRAIT d'abord envoyer une trame GOAWAY (Section 6.8) avec l'identifiant de flux du dernier flux qu'elle a reçu avec succès de son pair. La trame GOAWAY inclut un code d'erreur (Section 7) qui indique pourquoi la connexion se termine. Après l'envoi de la trame GOAWAY pour une condition d'erreur, l'extrémité DOIT fermer la connexion TCP.
Il est possible que le GOAWAY ne soit pas reçu de manière fiable par l'extrémité réceptrice. En cas d'erreur de connexion, GOAWAY fournit uniquement une tentative au mieux de communiquer avec le pair sur la raison pour laquelle la connexion est terminée.
Une extrémité peut mettre fin à une connexion à tout moment. En particulier, une extrémité PEUT choisir de traiter une erreur de flux comme une erreur de connexion. Les extrémités DEVRAIENT envoyer une trame GOAWAY lors de la fin d'une connexion, à condition que les circonstances le permettent.
5.4.2. Stream Error Handling (Gestion des Erreurs de Flux)
Une erreur de flux est une erreur liée à un flux spécifique qui n'affecte pas le traitement des autres flux.
Une extrémité qui détecte une erreur de flux envoie une trame RST_STREAM (Section 6.4) qui contient l'identifiant de flux du flux où l'erreur s'est produite. La trame RST_STREAM inclut un code d'erreur qui indique le type d'erreur.
Un RST_STREAM est la dernière trame qu'une extrémité peut envoyer sur un flux. Le pair qui envoie la trame RST_STREAM DOIT être prêt à recevoir toutes les trames qui ont été envoyées ou mises en file d'attente pour l'envoi par le pair distant. Ces trames peuvent être ignorées, sauf lorsqu'elles modifient l'état de la connexion (tel que l'état maintenu pour la compression de section de champ (Section 4.3) ou le contrôle de flux).
Normalement, une extrémité NE DEVRAIT PAS envoyer plus d'une trame RST_STREAM pour un flux donné. Cependant, une extrémité PEUT envoyer des trames RST_STREAM supplémentaires si elle reçoit des trames sur un flux fermé après plus d'un temps d'aller-retour. Ce comportement est autorisé pour traiter les implémentations mal comportées.
Pour éviter les boucles, une extrémité NE DOIT PAS envoyer un RST_STREAM en réponse à une trame RST_STREAM.
5.4.3. Connection Termination (Terminaison de Connexion)
Si la connexion TCP est fermée ou réinitialisée alors que les flux restent dans les états « open » ou « half-closed », alors les flux affectés ne peuvent pas être automatiquement retentés (voir Section 8.7 pour plus de détails).
5.5. Extending HTTP/2 (Extension d'HTTP/2)
HTTP/2 permet l'extension du protocole. Dans les limites décrites dans cette section, les extensions de protocole peuvent être utilisées pour fournir des services supplémentaires ou modifier tout aspect du protocole. Les extensions ne sont efficaces que dans le cadre d'une seule connexion HTTP/2.
Cela s'applique aux éléments de protocole définis dans ce document. Cela n'affecte pas les options existantes pour l'extension d'HTTP, telles que la définition de nouvelles méthodes, codes de statut ou champs (voir Section 16 de [HTTP]).
Les extensions sont autorisées à utiliser de nouveaux types de trames (Section 4.1), de nouveaux paramètres (Section 6.5) ou de nouveaux codes d'erreur (Section 7). Des registres pour la gestion de ces points d'extension sont définis dans la Section 11 de [RFC7540].
Les implémentations DOIVENT ignorer les valeurs inconnues ou non prises en charge dans tous les éléments de protocole extensibles. Les implémentations DOIVENT rejeter les trames dont les types sont inconnus ou non pris en charge. Cela signifie que l'un de ces points d'extension peut être utilisé en toute sécurité par les extensions sans arrangement ou négociation préalable. Cependant, les trames d'extension qui apparaissent au milieu d'un bloc de champ (Section 4.3) ne sont pas autorisées ; celles-ci DOIVENT être traitées comme une erreur de connexion (Section 5.4.1) de type PROTOCOL_ERROR.
Les extensions DEVRAIENT éviter de modifier les éléments de protocole définis dans ce document ou les éléments pour lesquels aucun mécanisme d'extension n'est défini. Cela inclut les modifications de la disposition des trames, les ajouts ou modifications de la manière dont les trames sont composées en messages HTTP (Section 8.1), la définition de champs de pseudo-en-tête, ou les modifications de tout élément de protocole qu'une extrémité conforme pourrait traiter comme une erreur de connexion (Section 5.4.1).
Une extension qui modifie des éléments de protocole existants ou l'état DOIT être négociée avant d'être utilisée. Par exemple, une extension qui modifie la disposition de la trame HEADERS ne peut pas être utilisée tant que le pair n'a pas donné un signal positif que cela est acceptable. Dans ce cas, il pourrait également être nécessaire de coordonner le moment où la disposition révisée entre en vigueur. Par exemple, traiter des trames autres que les trames DATA comme contrôlées par flux nécessite un changement de sémantique que les deux extrémités doivent comprendre, donc cela ne peut être fait que par négociation.
Ce document ne mandate pas de méthode spécifique pour négocier l'utilisation d'une extension mais note qu'un paramètre (Section 6.5.2) pourrait être utilisé à cette fin. Si les deux pairs définissent une valeur qui indique la volonté d'utiliser l'extension, alors l'extension peut être utilisée. Si un paramètre est utilisé pour la négociation d'extension, la valeur initiale DOIT être définie de manière à ce que l'extension soit initialement désactivée.
Chapitre 5 terminé !