4. HTTP Frames (HTTP-Frames)
Sobald die HTTP/2-Verbindung hergestellt ist, können Endpunkte mit dem Austausch von Frames beginnen.
4.1. Frame Format (Frame-Format)
Alle Frames beginnen mit einem festen 9-Oktett-Header, gefolgt von einer variablen Frame-Payload.
HTTP Frame {
Length (24),
Type (8),
Flags (8),
Reserved (1),
Stream Identifier (31),
Frame Payload (..),
}
Abbildung 1: Frame-Layout
Die Felder des Frame-Headers sind wie folgt definiert:
Length (Länge): Die Länge der Frame-Payload, ausgedrückt als vorzeichenlose 24-Bit-Ganzzahl in Oktett-Einheiten. Werte größer als 2^14 (16.384) dürfen nicht (MUST NOT) gesendet werden, es sei denn, der Empfänger hat einen größeren Wert für SETTINGS_MAX_FRAME_SIZE gesetzt.
Die 9 Oktette des Frame-Headers sind in diesem Wert nicht enthalten.
Type (Typ): Der 8-Bit-Typ des Frames. Der Frame-Typ bestimmt das Format und die Semantik des Frames. In diesem Dokument definierte Frames sind in Abschnitt 6 aufgelistet. Implementierungen müssen (MUST) Frames unbekannter Typen ignorieren und verwerfen.
Flags: Ein 8-Bit-Feld, das für boolesche Flags spezifisch für den Frame-Typ reserviert ist.
Flags werden Semantiken zugewiesen, die für den angegebenen Frame-Typ spezifisch sind. Ungenutzte Flags sind solche, die für einen bestimmten Frame-Typ keine definierten Semantiken haben. Ungenutzte Flags müssen (MUST) beim Empfang ignoriert werden und müssen (MUST) beim Senden nicht gesetzt bleiben (0x00).
Reserved (Reserviert): Ein reserviertes 1-Bit-Feld. Die Semantik dieses Bits ist nicht definiert, und das Bit muss (MUST) beim Senden nicht gesetzt bleiben (0x00) und muss (MUST) beim Empfang ignoriert werden.
Stream Identifier (Stream-Identifikator): Ein Stream-Identifikator (siehe Abschnitt 5.1.1), ausgedrückt als vorzeichenlose 31-Bit-Ganzzahl. Der Wert 0x00 ist für Frames reserviert, die mit der Verbindung als Ganzes im Gegensatz zu einem einzelnen Stream verbunden sind.
Die Struktur und der Inhalt der Frame-Payload hängen vollständig vom Frame-Typ ab.
4.2. Frame Size (Frame-Größe)
Die Größe einer Frame-Payload ist durch die maximale Größe begrenzt, die ein Empfänger in der Einstellung SETTINGS_MAX_FRAME_SIZE ankündigt. Diese Einstellung kann jeden Wert zwischen 2^14 (16.384) und 2^24-1 (16.777.215) Oktetten haben (einschließlich).
Alle Implementierungen müssen (MUST) in der Lage sein, Frames mit einer Länge von bis zu 2^14 Oktetten plus dem 9-Oktett-Frame-Header (Abschnitt 4.1) zu empfangen und minimal zu verarbeiten. Die Größe des Frame-Headers ist bei der Beschreibung von Frame-Größen nicht enthalten.
Hinweis: Bestimmte Frame-Typen, wie PING (Abschnitt 6.7), erlegen zusätzliche Grenzen für die zulässige Menge an Frame-Payload-Daten auf.
Ein Endpunkt muss (MUST) einen Fehlercode FRAME_SIZE_ERROR senden, wenn ein Frame die in SETTINGS_MAX_FRAME_SIZE definierte Größe überschreitet, eine für den Frame-Typ definierte Grenze überschreitet oder zu klein ist, um obligatorische Frame-Daten zu enthalten. Ein Frame-Größenfehler in einem Frame, der den Zustand der gesamten Verbindung ändern könnte, muss (MUST) als Verbindungsfehler (Connection Error, Abschnitt 5.4.1) behandelt werden; dies umfasst jeden Frame, der einen Feldblock (Field Block, Abschnitt 4.3) trägt (d.h. HEADERS, PUSH_PROMISE und CONTINUATION), einen SETTINGS-Frame und jeden Frame mit einer Stream-ID von 0.
Endpunkte sind nicht verpflichtet, den gesamten verfügbaren Platz in einem Frame zu nutzen. Die Reaktionsfähigkeit kann verbessert werden, indem Frames verwendet werden, die kleiner als die maximal zulässige Größe sind. Das Senden großer Frames kann zu Verzögerungen beim Senden zeitkritischer Frames (wie RST_STREAM, WINDOW_UPDATE oder PRIORITY) führen, die, wenn sie durch die Übertragung eines großen Frames blockiert werden, die Leistung beeinträchtigen könnten.
4.3. Field Section Compression and Decompression (Feldabschnittkompression und -dekompression)
Feldabschnittkompression (Field Section Compression) ist der Prozess der Kompression eines Satzes von Feldzeilen (Abschnitt 5.2 von [HTTP]) zur Bildung eines Feldblocks (Field Block). Feldabschnittdekompression (Field Section Decompression) ist der Prozess der Dekodierung eines Feldblocks in einen Satz von Feldzeilen. Details zur HTTP/2-Feldabschnittkompression und -dekompression sind in [COMPRESSION] definiert, das aus historischen Gründen diese Prozesse als Header-Kompression und -Dekompression bezeichnet.
Jeder Feldblock trägt alle komprimierten Feldzeilen eines einzelnen Feldabschnitts. Header-Abschnitte enthalten auch Kontrolldaten, die mit der Nachricht in Form von Pseudo-Header-Feldern (Pseudo-Header Fields, Abschnitt 8.3) verknüpft sind, die dasselbe Format wie eine Feldzeile verwenden.
Hinweis: RFC 7540 [RFC7540] verwendete den Begriff "Header-Block (Header Block)" anstelle des generischeren "Feldblock (Field Block)".
Feldblöcke tragen Kontrolldaten und Header-Abschnitte für Anfragen, Antworten, versprochene Anfragen und gepushte Antworten (siehe Abschnitt 8.4). Alle diese Nachrichten können optional, mit Ausnahme von Zwischenantworten und Anfragen, die in PUSH_PROMISE-Frames (Abschnitt 6.6) enthalten sind, einen Feldblock enthalten, der einen Trailer-Abschnitt trägt.
Ein Feldabschnitt ist eine Sammlung von Feldzeilen. Jede der Feldzeilen in einem Feldblock trägt einen einzelnen Wert. Der serialisierte Feldblock wird dann in eine oder mehrere Oktettsequenzen unterteilt, die als Feldblockfragmente (Field Block Fragments) bezeichnet werden. Das erste Feldblockfragment wird innerhalb der Frame-Payload von HEADERS (Abschnitt 6.2) oder PUSH_PROMISE (Abschnitt 6.6) übertragen, von denen jeder von CONTINUATION-Frames (Abschnitt 6.10) gefolgt sein kann, um nachfolgende Feldblockfragmente zu tragen.
Das Cookie-Header-Feld [COOKIE] wird durch das HTTP-Mapping speziell behandelt (siehe Abschnitt 8.2.3).
Ein empfangender Endpunkt setzt den Feldblock durch Verkettung seiner Fragmente wieder zusammen und dekomprimiert dann den Block, um den Feldabschnitt zu rekonstruieren.
Ein vollständiger Feldabschnitt besteht aus:
-
einem einzelnen HEADERS- oder PUSH_PROMISE-Frame mit gesetztem END_HEADERS-Flag, oder
-
einem HEADERS- oder PUSH_PROMISE-Frame mit nicht gesetztem END_HEADERS-Flag und einem oder mehreren CONTINUATION-Frames, wobei der letzte CONTINUATION-Frame das END_HEADERS-Flag gesetzt hat.
Jeder Feldblock wird als diskrete Einheit verarbeitet. Feldblöcke müssen (MUST) als zusammenhängende Sequenz von Frames übertragen werden, ohne verschachtelte Frames eines anderen Typs oder von einem anderen Stream. Der letzte Frame in einer Sequenz von HEADERS- oder CONTINUATION-Frames hat das END_HEADERS-Flag gesetzt. Der letzte Frame in einer Sequenz von PUSH_PROMISE- oder CONTINUATION-Frames hat das END_HEADERS-Flag gesetzt. Dies ermöglicht es, dass ein Feldblock logisch einem einzelnen Frame entspricht.
Feldblockfragmente können nur als Frame-Payload von HEADERS-, PUSH_PROMISE- oder CONTINUATION-Frames gesendet werden, da diese Frames Daten tragen, die den vom Empfänger verwalteten Kompressionskontext ändern können. Ein Endpunkt, der HEADERS-, PUSH_PROMISE- oder CONTINUATION-Frames empfängt, muss Feldblöcke wieder zusammensetzen und Dekompression durchführen, selbst wenn die Frames verworfen werden sollen. Ein Empfänger muss (MUST) die Verbindung mit einem Verbindungsfehler (Abschnitt 5.4.1) vom Typ COMPRESSION_ERROR beenden, wenn er einen Feldblock nicht dekomprimiert.
Ein Dekodierungsfehler in einem Feldblock muss (MUST) als Verbindungsfehler (Abschnitt 5.4.1) vom Typ COMPRESSION_ERROR behandelt werden.
4.3.1. Compression State (Kompressionszustand)
Feldkompression ist zustandsbehaftet. Jeder Endpunkt hat einen HPACK-Encoder-Kontext und einen HPACK-Decoder-Kontext, die zum Kodieren und Dekodieren aller Feldblöcke auf einer Verbindung verwendet werden. Abschnitt 4 von [COMPRESSION] definiert die dynamische Tabelle, die der primäre Zustand für jeden Kontext ist.
Die dynamische Tabelle hat eine maximale Größe, die von einem HPACK-Decoder festgelegt wird. Ein Endpunkt kommuniziert die von seinem HPACK-Decoder-Kontext gewählte Größe über die Einstellung SETTINGS_HEADER_TABLE_SIZE; siehe Abschnitt 6.5.2. Wenn eine Verbindung hergestellt wird, beginnt die Größe der dynamischen Tabelle für den HPACK-Decoder und -Encoder an beiden Endpunkten bei 4.096 Bytes, dem Anfangswert der Einstellung SETTINGS_HEADER_TABLE_SIZE.
Jede Änderung des mit SETTINGS_HEADER_TABLE_SIZE festgelegten Maximalwerts wird wirksam, wenn der Endpunkt Einstellungen bestätigt (Abschnitt 6.5.3). Der HPACK-Encoder an diesem Endpunkt kann die dynamische Tabelle auf jede Größe bis zum vom Decoder festgelegten Maximalwert setzen. Ein HPACK-Encoder deklariert die Größe der dynamischen Tabelle mit einer Dynamic Table Size Update-Anweisung (Abschnitt 6.3 von [COMPRESSION]).
Sobald ein Endpunkt eine Änderung von SETTINGS_HEADER_TABLE_SIZE bestätigt, die das Maximum unter die aktuelle Größe der dynamischen Tabelle reduziert, muss (MUST) sein HPACK-Encoder den nächsten Feldblock mit einer Dynamic Table Size Update-Anweisung beginnen, die die dynamische Tabelle auf eine Größe setzt, die kleiner oder gleich dem reduzierten Maximum ist; siehe Abschnitt 4.2 von [COMPRESSION]. Ein Endpunkt muss (MUST) einen Feldblock, der einer Bestätigung der Reduktion auf die maximale dynamische Tabellengröße folgt, als Verbindungsfehler (Abschnitt 5.4.1) vom Typ COMPRESSION_ERROR behandeln, wenn er nicht mit einer konformen Dynamic Table Size Update-Anweisung beginnt.
Hinweis: Implementierer werden darauf hingewiesen, dass die Reduzierung des Werts von SETTINGS_HEADER_TABLE_SIZE nicht weitreichend interoperabel ist. Die Verwendung der Verbindungspräambel zur Reduzierung des Werts unter den Anfangswert von 4.096 wird etwas besser unterstützt, könnte jedoch bei einigen Implementierungen fehlschlagen.