HTTP Hypertext Transfer Protocol
HTTP/1.0 allows one outstanding request per TCP connection
HTTP/1.1 adds request pipelining
suffers from head-of-line blocking
HeaderField can be repetitive and verbose
HTTP/2 supports all core features of HTTP/1.1
can interleave requests and responses per TCP connection
can prioritize requests
can use fewer TCP connections
HeaderField uses efficient coding
uses binary message framing
is an application-layer protocol
runs on top of TCP
uses same "http" and "https" URI schemes as HTTP/1.1
port 80 for "http" URIs
443 for "https" URIs
Client initiates TCP connection
ask if Server supports HTTP/2
VersionIdentifier negotiation implies use of HTTP/2
"h2c" means HTTP/2 over TCP without TLS
reserved from ALPN identifier space
"h2" means HTTP/2 over TLS
used in TLS-ALPN extension field RFC7301
ALPN identifier = {0x68,0x32}
StartSteps "h2c" noKnow Client does not know if Server supports HTTP/2
request "http" URI using HTTP/1.1
HeaderField Upgrade = "h2c"
HTTP2-Settings only one
if has payload body
then Client sends payload body before sending HTTP/2 frames
example GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
stream StreamIdentifier = 1
state "half-closed (local)" to Client
default priority
may use OPTIONS request to upgrade HTTP/1.1 to HTTP/2
costing one more RTT
Server receives Client request
if does not support HTTP/2
then ignores Upgrade
responds example HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html
...
if supports HTTP/2 and
accepts upgrade
then ignore "h2" token in Upgrade HeaderField
respods 101(Switching Protocols)
HTTP/2 frames have ConnectionPreface
response to client request
example HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c
[ HTTP/2 connection ...
Client receives 101 response
sends ConnectionPreface
yeKnow Client knows Server supports HTTP/2
may know using RFC7838
sends ConnectionPreface
then may immediately send HTTP request
Server receives ConnectionPreface
identifies HTTP/2 by presence of ConnectionPreface
sends ConnectionPreface
"h2" Client may or not know if Server supports HTTP/2
request to an "https" URI using TLS-ALPN extension
completes TLS handshake
sends ConnectionPreface
Server receives request
sends ConnectionPreface
HTTP2-Settings = token68 ABNF production RFC5234
RFC7230 Section 2.1
only sent by Client
only for request to upgrade HTTP/1.1 to HTTP/2
only one per request
if not in request then Server does not upgrade to HTTP/2
ConnectionPreface = strg || sttngsFrmC if sent by Client
= sttngsFrmS if sent by Server
strg = 0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
designed so that intermediaries do not attempt to process further frames
sttngsFrameC Client SETTINGS frame
may be empty
sttngsFrameS Server SETTINGS frame
may be empty
if receive invalid ConnectionPreface
then send Connection error PROTOCOL_ERROR
may not send GOAWAY since peer may not be using HTTP/2
HTMLHeader SenderSteps put one or more HeaderField in HeaderList
serialize HeaderList into HeaderBlock using HeaderCompression
divided HeaderBlock into HeaderBlockFragments
put HeaderBlockFragments in Payload of Frames
Frames are transmitted to peer
receiverSteps concatenate HeaderBlockFragments into HeaderBlock
HeaderDeCompression
reconstruct HeaderList
read HeaderFields of HeaderList
HeaderField same as in HTTP/1
HeaderBlock apply HeaderDeCompression even if data will be discarded
is always processed to maintain correct connection state
except if connection closes
if server receives very large HeaderBlock
then server may send HTTP 431 (Request Header Fields Too Large) status code RFC6585
HeaderBlockFragments made of one or more octet sequences
put in Payload of one HEADERS Frame followed by zero or more CONTINUATION Frames
one PUSH_PROMISE Frame followed by zero or more CONTINUATION Frames
transmitted with no Frame of other Type interleaved
stream interleaved
HeaderCompression RFC7541
is statefull
if abused by waste of processing
then send stream error ENHANCE_YOUR_CALM
Stream created and used unilaterally
may be closed by Client or Server
has Frames exchanged between Client and Server
processed in receiving order
with independent sequence
bidirectional sequence
States +--------+
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 |
`----------------------->| |<----------------------'
+--------+
map shows stream state transitions
frames and flags affecting only those transitions
send endpoint sends this Frame
recv endpoint receives this Frame
H HEADERS Frame followed by zero or more CONTINUATION Frames
PP PUSH_PROMISE Frame followed by zero or more CONTINUATION Frames
R RST_STREAM Frame
ES Frame with END_STREAM bit set
processed as separate event to Frame that has it
HEADERS frame with END_STREAM bit set causes two state transitions
is interpreted as H and ES
CONTINUATION frame does not result in state transitions
PRIORITY frame may be sent and received in any state
if receive Frame and
this description doesnt say what to do
then may send Connection error PROTOCOL_ERROR
"idle" starting state
if send or receive HEADERS Frame then "open"
if send or receive HEADERS Frame with END_STREAM bit set then "half-closed"
if send PUSH_PROMISE frame on another stream then "reserved (local)" for reserved stream
if receive PUSH_PROMISE frame on another stream then "reserved (remote)" for reserved stream
PUSH_PROMISE frame reserves "idle" stream identified in PromisedStreamID
is not sent on "idle" stream
if receive Frame with no HEADERS or PRIORITY
then send connection error PROTOCOL_ERROR
"reserved (local)" state after sending PUSH_PROMISE frame
if send HEADERS frame then "half-closed (remote)"
if send or receive RST_STREAM frame then "closed" and
release stream reservation
if send Frame with no HEADERS or
RST_STREAM or
PRIORITY then error
if receive Frame with no RST_STREAM or
PRIORITY or
WINDOW_UPDATE
then send connection error PROTOCOL_ERROR
"reserved (remote)" stream reserved by peer
if receive HEADERS Frame then "half-closed (local)"
if send or receive RST_STREAM Frame then "closed"
release stream reservation
may send PRIORITY Frame to reprioritize reserved stream
if send Frame with no RST_STREAM or
WINDOW_UPDATE or
PRIORITY then error
if receive Frame with no HEADERS or
RST_STREAM or
PRIORITY
then connection error PROTOCOL_ERROR
"open" may send or receive Frames with any Type
sender observes advertised stream-level FlowControl limits
if send Frame END_STREAM bit set then "half-closed (local)"
if receive Frame END_STREAM bit set then "half-closed (remote)"
if send or receive RST_STREAM Frame then "closed"
"half-closed (local)" may receive Frames with any Type
if send Frames with no WINDOW_UPDATE or
PRIORITY or
RST_STREAM then error
if receive Frame END_STREAM bit set then "closed"
if send or receive RST_STREAM Frame then "closed"
may send WINDOW_UPDATE Frame for FlowControl
if receive Frame END_STREAM bit set
then ignore the following WINDOW_UPDATE Frames
"half-closed (remote)" do not maintain peer FlowControl window
if receive Frames with no WINDOW_UPDATE or
RST_STREAM or
PRIORITY
then send stream error STREAM_CLOSED
may send frames of any type
observe advertised stream-level FlowControl limits
if send Frame END_STREAM bit set then "closed"
if send or receive RST_STREAM Frame then "closed"
"closed" terminal state
if receive RST_STREAM Frame and
receive Frame with no PRIORITY after
then send stream error STREAM_CLOSED
if receive Frame END_STREAM bit set and
receive Frame with any Type after
then stream error STREAM_CLOSED
if send DATA or HEADERS with END_STREAM bit set
then may receive WINDOW_UPDATE or RST_STREAM for a short period
and must ignore Frames
may send connection error PROTOCOL_ERROR
if peer has not received and processed RST_STREAM or END_STREAM
then peer may send WINDOW_UPDATE or RST_STREAM
if receive PRIORITY Frame and
stream has been removed from dependency tree
then may ignore PRIORITY Frame
if sent RST_STREAM in previous state and
state became "closed" and
receive any Frames after then ignore received Frames
may send error
if sent RST_STREAM and
receive FlowControl Frame for example DATA
then count FlowControl Frame toward FlowControl window
if sent RST_STREAM and
received PUSH_PROMISE after and
PUSH_PROMISE is not wanted then send RST_STREAM
StreamIdentifier = odd if stream initiated by Client
even if stream initiated by Server
0 is used for connection control
not used to establish new stream
> any stream previously created by endpoint
if = unexpected value then send connection error PROTOCOL_ERROR
if send or receive Frame in new stream and
other stream is "idle" and
"idle" stream StreamIdentifier < new stream
then "idle" stream becomes "closed"
example if Client never sends Frame on stream 5 and
sends HEADERS Frame on stream 7
then stream 5 becomes "closed"
if Client wants to create new stream and
StreamIdentifier value range is exhausted
then Client creates new connection
if Server wants to create new stream and
StreamIdentifier value range is exhausted
then Server sends GOAWAY Frame
then Client opens new connection
Priority set using HEADERS Frame
PRIORITY Frame
allows endpoint to express how peer may allocate resources when managing concurrent streams
does not forces peer to process concurrent streams in a particular order
depends on Dependency
Weight
for new Stream Dependency = 0
Weight = 16
Dependency used by marking Stream as dependent on other stream
parent is a stream upon which stream is dependent
children may get resources only if parents are "closed" or blocked
0 non-existent stream
root of tree
parent of parents
if stream depends on itself then send stream error PROTOCOL_ERROR
if stream has no parent then stream Dependency = 0
if stream is "idle" then stream is not in tree
if stream is not in tree then children get Dependency = 0
Weight = 16
DefaultFlag StreamIdentifier is added as new child to StreamDependency
chirdren sharing parent are not ordered with respect to each other
example if B and C are the children of A
then B and C and D become the children of A
map A A
/ \ ==> /|\
B C B C D
ExclusiveFlag children of StreamDependency become children of StreamIdentifier
StreamIdentifier becomes the child of StreamDependency
example if B and C are the children of A
then B and C become the children of D
D becomes the child of A
map A
A |
/ \ ==> D
B C / \
B C
if stream is reprioritized then children move with stream
example stream is made dependent on own dependencies
B and C depend on A
D and E depend on C
F depends on D
if A is made dependent on D
then D takes the place of A
all other dependency relationships stay the same
if reprioritization is exclusive
then F becomes dependent on A
map x x x x
| / \ | |
A D A D D
/ \ / / \ / \ |
B C ==> F B C ==> F A OR A
/ \ | / \ /|\
D E E B C F B C
| | |
F E E
(intermediate) (non-exclusive) (exclusive)
if stream1 is the child of stream2 and
stream1 is removed from tree
then Weight of stream1 is distributed to children of stream1
children of stream1 become children of stream2
example map P
/ \
A B
/ \
C D
streams A and B share parent and
C and D depend on A
if A and D are blocked
then C receives all resources of A
if A is removed from tree
then A Weight is divided between C and D
if C and D have same Weight and
A is removed from tree and
D is blocked
then C receives 1/3 not 1/2 of resources
if Stream becomes "closed"
then endpoint may retain Stream Priority state for a period
to avoid giving incorrect Priority to new dependent Streams
if endpoint is under high load
then endpoint may discard parts of Priority state
Weight >= 1
<= 256
proportional to resources allocation
bigger means more resources
example if B has Weight 4 and parent A and
C has Weight 12 and parent A and
A is blocked then B should receive 1/3 of resources compared to C
Frame = Header || Payload
Header +-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| StreamIdentifier (31) |
+-+-------------------------------------------------------------+
Length of Payload
unsigned integer
<= SETTINGS_MAX_FRAME_SIZE
size = 24bit
Type determines Frame format and semantics
if receive unknown then ignore and discard Frame
size = 8bit
Flags each bit has different use
size = 8bit
R = 0
ignored
size = 1bit
StreamIdentifier unsigned integer
if = 0 then Frame is associated with whole Connection
if != 0 then Frame is associated with individual stream
size = 31bit
DATA Header Type = 0
Flags PADDED bit 3
if set then PadLength and Padding are present
if not set then PadLength and Padding are not present
END_STREAM bit 0
if set then this is last Frame to send for stream
Payload +---------------+
|PadLength? (8)|
+---------------+-----------------------------------------------+
| Data (*) ...
+---------------------------------------------------------------+
| Padding (*) ...
+---------------------------------------------------------------+
PadLength in octets
size = 8bit
if >= Frame Header Length then receiver connection error PROTOCOL_ERROR
may = 0
Data Application data
may carry HTTP request or response payloads
payload body RFC7230 Section 3.3
size = Frame Header Length - size of PadLength - PadLength octets
Padding has no application semantic value
may obscure size of messages
= 0
if != 0 then receiver may connection error PROTOCOL_ERROR
included in FlowControl
only sent if stream is "open" or "half-closed (remote)"
if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR
HEADERS Header Type = 1
Flags END_STREAM bit 0
if set then this is last HeaderBlock in Stream to send
this Frame may be followed by CONTINUATION frame and still be last HeaderBlock in stream
END_HEADERS bit 2
if set then this frame is not followed by CONTINUATION frame
if not set then this frame is followed by CONTINUATION frame
if set and receive frame in this or different stream
then connection error PROTOCOL_ERROR
allows HeaderBlock to be logically equivalent to one Frame
PADDED bit 3
if set then PadLength and Padding are present
if not set then PadLength and Padding are not present
PRIORITY bit 5
if set then E and StreamDependency and Weight are present
if not set then E and StreamDependency and Weight are not present
enabled present data is equivalent to PRIORITY Frame
reprioritizes Stream if bit set and in subsequent HEADERS to firt on Stream
Payload +---------------+
|PadLength? (8)|
+-+-------------+-----------------------------------------------+
|E| StreamDependency? (31) |
+-+-------------+-----------------------------------------------+
| Weight? (8) |
+-+-------------+-----------------------------------------------+
| HeaderBlockFragment (*) ...
+---------------------------------------------------------------+
| Padding (*) ...
+---------------------------------------------------------------+
PadLength length of Padding
in octets
size = 8bit
if >= Frame Header Length then connection error PROTOCOL_ERROR
E if set then StreamDependency is exclusive
size = 1bit
StreamDependency identifies the parent of this stream
size = 31bit
Weight unsigned integer
Priority Weight of this stream
add one to obtain value between 1 and 256
size = 8bit
sent on stream in "idle" or
"open" or
"reserved (local)" or
"half-closed (remote)"
if HeaderBlock does not fit in one HEADERS
then HeaderBlock is continued in one or more CONTINUATION Frames
only appears at start or end of stream
if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR
PRIORITY Header Type = 2
Flags none
Payload +-+-------------------------------------------------------------+
|E| StreamDependency (31) |
+-+-------------+-----------------------------------------------+
| Weight (8) |
+-+-------------+
E indicates StreamDependency is exclusive
size = 1bit
StreamDependency identifies the parent of this stream
size = 31bit
Weight unsigned integer
Priority Weight of this stream
add one to obtain value between 1 and 256
size = 8bit
if size != 5 octets then send stream error FRAME_SIZE_ERROR
sent in any stream state
not sent between consecutive Frames with single HeaderBlock
if abused causing unnecessary waste of resources
then send stream error ENHANCE_YOUR_CALM
if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR
RST_STREAM Header Type = 3
Flags none
Payload +---------------------------------------------------------------+
| ErrorCode (32) |
+---------------------------------------------------------------+
unsigned integer
indicates why stream is being terminated
if size != 32bit then send connection error FRAME_SIZE_ERROR
immediately terminates stream
if received then send no additional Frame in stream except PRIORITY
RST_STREAM Frame
if sent then it takes time to arrive to peer
sender may receive Frames
must process received PUSH_PROMISE Frames
FlowControl Frames
HeaderCompression Frames
if sent and receive Frame on "closed" stream after more than one RTT
then may send again to deal with misbehaving implementations
if received with ErrorCode = REFUSED_STREAM
then stream is being closed prior to any processing having occurred
request sent on this stream are safe to retry
if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR
SETTINGS Header Type = 4
Flags ACK bit 0
if set then sender ACKnowledges receiving and applying this Frame
Payload is empty else send connection error FRAME_SIZE_ERROR
Payload has zero or more parameters
each Parameter +-------------------------------+
| Identifier (16) |
+-------------------------------+-------------------------------+
| Value (32) |
+---------------------------------------------------------------+
Parameters defined here are all supported by implementations
are not negotiated
affects receiver
last one received is applied
all processed in appearing order with no other Frame processing in between
different values for same Parameter can be advertised by each peer
if receive unknown or unsupported then ignore
SETTINGS_HEADER_TABLE_SIZE Identifier = 1
Value in octets
= 4096 if initial value
max size of HeaderCompression table
used to decode HeaderBlock
HeaderCompression encoder uses size <= Value
SETTINGS_ENABLE_PUSH Identifier = 2
Value = 1 if initial value
indicates server push is permitted
if = 0 then do not send PUSH_PROMISE frame
if != 0 or != 1 then send connection error PROTOCOL_ERROR
if sent = 0 and
ACKnowledged and
receive PUSH_PROMISE then send connection error PROTOCOL_ERROR
if Client receives SETTINGS_ENABLE_PUSH != 0
then send connection error PROTOCOL_ERROR
SETTINGS_MAX_CONCURRENT_STREAMS Identifier = 3
Value number of streams sender permits receiver to create
>= 100 is recomended
0 prevents creation of new streams
does not prohibit sending PUSH_PROMISE
initially there is no limit
only counts Streams in "open" or
"half-closed (local)" or
"half-closed (remote)"
if exceeded then send stream error PROTOCOL_ERROR or REFUSED_STREAM
if endpoints wants Value < current concurrent streams
then endpoint closes stream or
waits for current concurrent streams to go down
SETTINGS_INITIAL_WINDOW_SIZE Identifier = 4
Value receiver updates all streams WindowSizeS#s
does not affect WindowSizeCs
in octets
= 2^16-1 if initial value
< 2^31-1 else send connection error FLOW_CONTROL_ERROR
SETTINGS_MAX_FRAME_SIZE Identifier = 5
Value size of largest Frame Payload sender is willing to receive
in octets
= 2^14 if initial value
>= 2^14 else connection error PROTOCOL_ERROR
< 2^24 else connection error PROTOCOL_ERROR
SETTINGS_MAX_HEADER_LIST_SIZE Identifier = 6
Value max size of HeaderList sender accepts
in octets
initially there is no limit
must be sent by both endpoints at start of connection
may be sent by both endpoints at any other time of connection
always apply to connection
never apply to single stream
if received and ACK not set
then update received Parameters as soon as possible
send immediately SETTINGS Frame with ACK set
if sent and does not receive ACKnowledgement and
reasonable amount of time passes then may send connection error SETTINGS_TIMEOUT
if abused by pointlessly changing it or
setting multiple undefined parameters
then send stream error ENHANCE_YOUR_CALM
if StreamIdentifier != 0 then send connection error PROTOCOL_ERROR
if badly formed or incomplete then send connection error PROTOCOL_ERROR
if Frame Length != multiple of 6 octets then send connection error FRAME_SIZE_ERROR
PUSH_PROMISE Header Type = 5
Flags END_HEADERS bit 2
if set then this Frame has entire HeaderBlock
is not followed by one or more CONTINUATION Frame
if not set then this Frame is followed by one or more CONTINUATION Frame
if not set and
receive frame without CONTINUATION or
frame on different stream
then send connection error PROTOCOL_ERROR
PADDED bit 3
if set then PadLength and Padding are present
if not set then PadLength and Padding are not present
Payload +---------------+
|PadLength? (8) |
+-+-------------+-----------------------------------------------+
|R| PromisedStreamID (31) |
+-+-----------------------------+-------------------------------+
| HeaderBlockFragment (*) ...
+---------------------------------------------------------------+
| Padding (*) ...
+---------------------------------------------------------------+
PadLength length of Padding
in octets
size = 8bit
R reserved
size = 1bit
PromisedStreamID unsigned integer
identifies stream that will be initiated by Server
if received and
stream PromisedStreamID is not "idle"
then send connection error PROTOCOL_ERROR
changes promised stream to "reserved"
only reserves for later use
size = 31bit
HeaderBlockFragment provides additional context for promised stream
may modify state of HeaderCompression
has ":authority"
if ":authority" is not authoritative
then send stream error PROTOCOL_ERROR
has ":method" that is safe and cacheable else send stream error PROTOCOL_ERROR
is not sent by client
only send on stream in "open" or "half-closed (remote)"
promised streams may not be used in order promised
if not cacheable or RFC7231 Section 4.2.3
not safe or RFC7231 Section 4.2.1
has request body
then reset stream PromisedStreamID with stream error PROTOCOL_ERROR
if received then may reject promised streams
by returning RST_STREAM with promised StreamIdentifier
if received and ignored then stream state becomes indeterminate
if received in stream in neither "open" nor "half-closed (local)"
then connection error PROTOCOL_ERROR
if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR
PING Header Type = 6
Flags ACK bit 0
Payload +---------------------------------------------------------------+
| |
| OpaqueData (64) |
| |
+---------------------------------------------------------------+
OpaqueData has any value sender wants
used in any fashion by sender
size = 64bit
if received with ACK flag not set
then send PING frame with ACK flag set
identical Payload
may higher priority than any other frame
RTT round trip time
= time it takes for PING with ACK not set to go +
time it takes for PING with ACK set to come
determines whether idle connection is functional
sent from any endpoint
if StreamIdentifier != 0 then send connection error PROTOCOL_ERROR
if Frame Length != 8 then send connection error FRAME_SIZE_ERROR
GOAWAY Header Type = 7
Flags none
Payload +-+-------------------------------------------------------------+
|R| LastStreamID (31) |
+-+-------------------------------------------------------------+
| ErrorCode (32) |
+---------------------------------------------------------------+
| AdditionalDebugData (*) |
+---------------------------------------------------------------+
LastStreamID unsigned integer
highest stream sender might have taken some action on
yet take action on
initiated by receiver
= 0 if no streams data was processed
size = 31bit
ErrorCode reason for closing connection
size = 32bit
AdditionalDebugData for diagnostic purposes only
carries no semantic value
may have security or private data
if contains logged or otherwise persistently stored data
then do adequate safeguards to prevent unauthorized access
use to initiate shutdown of connection or
signal serious error conditions
gracefully stop accepting new streams while finishing processing established streams
applies to connection
does not apply to specific stream
if StreamIdentifier != 0 then send connection error PROTOCOL_ERROR
may send before closing connection so peer knows if stream is partially processed
may not send before closing connection if peer is misbehaving
if sent then ignore new streams initiated by receiver
with StreamIdentifier > LastStreamID
if sent GOAWAY and
sent data on stream with StreamIdentifier > LastStreamID
then that stream is ignored
if received then do not open new streams on connection
may do new connection for new streams
if received and connection has no more uses
then may send GOAWAY frame before terminating connection
if GOAWAY was used and
Connection closed and
stream with StreamIdentifier <= LastStreamID was not closed
then reattempting requests is not possible
transactions is not possible
any protocol activity is not possible
idempotent actions is possible
HTTP GET,PUT,DELETE is possible
if GOAWAY was used and
Connection closed and
stream with StreamIdentifier > LastStreamID was not closed
then any protocol activity may be safely retried using new connection
if sent then may maintaining connection "open" until all streams complete
if endpoint wants to do gracefull connection shut down
then send GOAWAY with ErrorCode = NO_ERROR
LastStreamID = 2^31-1
wait at least one RTT
if no error hapens then send GOAWAY with ErrorCode = NO_ERROR
LastStreamID = real stream
if sent GOAWAY with ErrorCode NO_ERROR and
new ErrorCode happens
then may send GOAWAY with new ErrorCode
LastStreamID <= LastStreamID of first GOAWAY
indicating which streams could have been acted upon
if connection terminates without GOAWAY frame
then LastStreamID = 2^31-1
WINDOW_UPDATE Header Type = 8
Flags none
Payload +-+-------------------------------------------------------------+
|R| WindowSizeIncrement (31) |
+-+-------------------------------------------------------------+
R reserved
size = 1bit
WindowSizeIncrement unsigned integer
in octets
> 0
< 2^31
if = 0 then stream error PROTOCOL_ERROR
size = 31bit
if size != 4 then send connection error FRAME_SIZE_ERROR
FlowControl Frames are of Type DATA
future Extensions may add new Types
does not apply to AllHops example Server to midlebox1 to midlebox2 to Client
applies to each OneHop example Client to midlebox2 or
midlebox1 to midlebox2
uses WindowSize integer
can be negative
in octets
= 65535 if new connection or stream
each enpoint has for each Connection WindowSizeCs for sending
WindowSizeCr for receiving
Stream WindowSizeS#s for sending
WindowSizeS#r for receiving
if receive FlowControl Frame with StreamIdentifier = 3
Length > WindowSizeS3r
then either 1 process Frame
update WindowSizeS3r = WindowSizeS3r - Frame Length
WindowSizeCr = WindowSizeCr - Frame Length
receiving Frame Length > WindowSizeS3r may happen after sending small SETTINGS_INITIAL_WINDOW_SIZE
2 send connection error FLOW_CONTROL_ERROR
if receive FlowControl Frame with StreamIdentifier = 2
Length <= WindowSizeS2r
then process Frame
update WindowSizeS2r = WindowSizeS2r - Frame Length
WindowSizeCr = WindowSizeCr - Frame Length
FlowControl Frame can not have StreamIdentifier = 0
if want to send FlowControl Frame with StreamIdentifier = 5
Length > WindowSizeS5s
then do not send Frame
if want to send FlowControl Frame with StreamIdentifier = 4
Length <= WindowSizeS4s
then send Frame
update WindowSizeS4s = WindowSizeS4s - Frame Length
WindowSizeCs = WindowSizeCs - Frame Length
if receive FlowControl Frame and detect connection error then do not apply FlowControl
if receive FlowControl Frame and detect stream error then apply FlowControl
if receive WINDOW_UPDATE with StreamIdentifier = 0
then update WindowSizeCr = WindowSizeCr + WindowSizeIncrement
if receive WINDOW_UPDATE with StreamIdentifier = 1
then update WindowSizeS1r = WindowSizeS1r + WindowSizeIncrement
if any WindowSize >= 2^31 then send either GOAWAY with FLOW_CONTROL_ERROR
RST_STREAM with FLOW_CONTROL_ERROR
if connection is new and
client sends 60000 octets and
server sends SETTINGS_INITIAL_WINDOW_SIZE = 16000 octets
then client calcualtes WindowSizeS1s = 65535 when connection is new
WindowSizeS1s = 65535-60000 = 5535 when client sends 60000 octets
WindowSizeS1s = 5535 + (16000-65535) =-44000 when server sends SETTINGS_INITIAL_WINDOW_SIZE
implementations manage how to avoid head-of-line blocking
large bandwidth*delay problems RFC7323
SETTINGS can change WindowSize for streams in "open" or "half-closed (remote)"
if abused causing unnecessary waste of resources
then send stream error ENHANCE_YOUR_CALM
CONTINUATION Header Type = 9
Flags END_HEADERS bit 2
if set then this Frame ends HeaderBlock
if not set and next received Frame Type != CONTINUATION or
is from another stream
then send connection error PROTOCOL_ERROR
Payload +---------------------------------------------------------------+
| HeaderBlockFragment (*) ...
+---------------------------------------------------------------+
continues sequence of HeaderBlock fragments
any number of CONTINUATION frames can be sent
if received and previous Frame had no HEADERS or
PUSH_PROMISE or
CONTINUATION with END_HEADERS not set
then send connection error PROTOCOL_ERROR
if StreamIdentifier = 0 then send connection error PROTOCOL_ERROR
if size > SETTINGS_MAX_FRAME_SIZE or
size > max limit for Frame type or
size < min limit for Frame type then send error FRAME_SIZE_ERROR
if FRAME_SIZE_ERROR for Frame with HEADERS or
PUSH_PROMISE or
CONTINUATION or
SETTINGS or
StreamIdentifier = 0 then Connection error
sending big Frame may delay sending time-sensitive Frames example RST_STREAM or
WINDOW_UPDATE or
PRIORITY
if endpoints do not maintain synchronized view of connection state
then communication will fail
if abused by receiving many small or empty
then send stream error ENHANCE_YOUR_CALM
Error class ConnectionError if entire connection becomes unusable
StreamError if one stream becomes unusable
ConnectionError for error preventing further processing of frame layer or
corrupting any connection state
if encountered then may send Frame Type GOAWAY
StreamIdentifier of last successful Stream received
ErrorCode indicating why connection is terminating
close TCP connection
endpoint may end connection at any time
treat StreamError as ConnectionError
StreamError does not affect other Streams
if detected then send Frame Type RST_STREAM
StreamIdentifier where error occurred
ErrorCode
ErrorCode size = 32bit
if unknown or unsupported then trigger no special behavior
may treate as INTERNAL_ERROR
= 0 NO_ERROR associated condition is not a result of error
= may be in GOAWAY indicating graceful shutdown of connection
= 1 PROTOCOL_ERROR endpoint detected unspecific protocol error
= use if specific ErrorCode is not available
= 2 INTERNAL_ERROR sender encountered unexpected internal error
= 3 FLOW_CONTROL_ERROR sender detected peer violated flow-control protocol
= 4 SETTINGS_TIMEOUT sender sent SETTINGS frame and received no response in time
= 5 STREAM_CLOSED sender received frame on "half-closed" stream
= 6 FRAME_SIZE_ERROR sender received frame with invalid size
= 7 REFUSED_STREAM sender refused stream prior to performing application processing
= 8 CANCEL sender indicates stream is no longer needed
= 9 COMPRESSION_ERROR sender is unable to maintain HeaderCompression context for connection
= 10 CONNECT_ERROR connection established in response to CONNECT was reset or abnormally closed
= 11 ENHANCE_YOUR_CALM sender detected peer might be generating excessive load
= 12 INADEQUATE_SECURITY underlying transport properties do not meet minimum security requirements
= 13 HTTP_1_1_REQUIRED sender requires HTTP/1.1 instead of HTTP/2
all request and response semantics are preserved from HTTP/1.1 into HTTP/2
specification and requirements of HTTP/1.1 Semantics and Content RFC7231
Conditional Requests RFC7232
Range Requests RFC7233
Caching RFC7234
Authentication RFC7235
portions of Message Syntax and Routing RFC7230
such as HTTP and HTTPS URI schemes
are applicable in HTTP/2
HTTP exchange consumes single stream
Client request on new stream
starts with HEADERS
"open"
ends with Frame with END_STREAM set
"half-closed (local)" for Client
"half-closed (remote)" for Server
Server response on same stream
starts with HEADERS
ends with Frame END_STREAM set
"closed"
completes after Server sends or
client receives
Frame END_STREAM set and any CONTINUATION frames
if client has not finished sending full request and
server response does not depend on the rest to receive
then server may send complete response for example Frame with END_STREAM set
RST_STREAM with error NO_ERROR
then Client does not discard responses because NO_ERROR
may discard responses because other reasons
does not support upgrade to another protocol
message . one HEADERS followed by zero or more CONTINUATION with
HeadeFields RFC7230 Section 3.2
. zero or more DATA with
payload body
. only for HTML response
zero or more HEADERS each followed by zero or more CONTINUATION with
informational (1xx) HTTP responses RFC7230 Section 3.2
RFC7231 Section 6.2
. one HEADERS followed by zero or more CONTINUATION with
Trailer RFC7230 Section 4.1.2
if receive final (non-informational) status code and
HEADERS END_STREAM is not set
then treat as malformed
do not use "chunked" transfer encoding RFC7230 Section 4.1
101 (Switching Protocols) status code RFC7231 Section 6.2.2
HeaderField series of key-value pairs
list at https://www.iana.org/assignments/message-headers
Name strings of ASCII characters
compared in case-insensitive fashion
if uppercase in HTTP request or response
then treat as malformed
TE HeaderField may be present in request only with value "trailers"
do not use Connection HeaderField to indicate connection-specific HeaderFields
if message has connection-specific HeaderFields
then treat as malformed
if transforming HTTP/1.x message to HTTP/2
then remove HeaderFields nominated by Connection HeaderField
Connection HeaderField
may remove even if not nominated by Connection HeaderField
Keep-Alive
Proxy-Connection
Transfer-Encoding
Upgrade
Cookie uses ";" to delimit cookie-pairs or "crumbs"
does not follow list construction rules in HTTP RFC7230 Section 3.2.2
may be split into separate HeaderField each with one or more cookie-pairs
if finish HeaderDeCompression and
there are multiple Cookie
then concatenate all Cookie into single octet string
using 0x3B 0x20 = "; "
then pass to non-HTTP/2 context like HTTP/1.1 connection or
generic HTTP server application
example cookie: a=b
cookie: c=d
cookie: e=f
concatenates into
cookie: a=b; c=d; e=f
if HTTP request or response has payload body
then content-length HeaderField may be used
if response has no payload RFC7230 Section 3.3.2 and
no content in all DATA Frames
then response can have non-zero content-length HeaderField
if content-length HeaderField value != sum of DATA frame payload lengths forming body
then treat as malformed
PseudoHeaderField != HeaderField
begins with ':' character (ASCII 0x3a)
has target URI
method of request
status code for response
are not in trailing HeaderFields
if defined for HTTP requests then do not put in HTTP responses
if defined for HTTP responses then do not put in HTTP requests
if in request or response and is undefined or invalid then treat as malformed
if in request or response and is after HeaderField then treat as malformed
only use the ones defined here
all HTTP requests have at least one valid ":method" and ":scheme" and ":path"
else treat as malformed
responses have one ":status" else treat as malformed
request ":method" has HTTP method RFC7231 Section 4
":scheme" has scheme portion of target URI RFC3986 Section 3.1
not restricted to "http" and "https" schemed URIs
proxy or gateway can translate non-HTTP schemes
use HTTP to interact with non-HTTP services
":authority" has authority portion of target URI RFC3986 Section 3.2
no "userinfo" subcomponent for "http" or "https" schemed URIs
if translating HTTP/1.1 request with target in origin form
asterisk form RFC7230 Section 5.3
then ":authority" is omitted
if Client generates HTTP/2 requests directly
then should use ":authority" instead of Host HeaderField
if intermediary converts HTTP/2 request to HTTP/1.1 and
request has no Host HeaderField
then create Host HeaderField by copying ":authority" value
":path" has path and query parts of target URI
"path-absolute" production
optionally '?' character followed by "query" production RFC3986 Sections 3.3 and 3.4
'*' for request in asterisk form
if "http" or "https" URI has no path component
then ":path" = '/'
if "http" or "https" URI has no path component and
is an OPTIONS request
then ":path" = '*' RFC7230 Section 5.3.4
HTTP/2 has no way to carry version identifier of HTTP/1.1 request line
response ":status" has HTTP status code field RFC7231 Section 6
HTTP/2 has no way to carry version or reason phrase of HTTP/1.1 status line
Malformed if detected then send stream error PROTOCOL_ERROR
if detected by intermediary then intermediary does not forward message for example any intermediary not acting as tunnel
if detected in requests by server then server may send response before closing or resetting stream
if detected in response by Client then Client does not accept response
Padding does not replace TLS padding
only slows attacker by increasing number of frames to observe
provides little protection if using random padding with predictable distribution
if plaintext is padded to fixed size and
attacker makes payload cross the fixed size
then plaintext information will be exposed
intermediaries may retain padding of DATA
remove padding of HEADERS
PUSH_PROMISE
to improve data protection
HTTP/1.1equivalentHTTP/2 HTTP GET request has request HeaderFields
no payload body
example HEADERS frame has END_HEADERS and END_STREAM flags set
no CONTINUATION frames sent
equivalence GET /resource HTTP/1.1 HEADERS
Host: example.org ==> + END_STREAM
Accept: image/jpeg + END_HEADERS
:method = GET
:scheme = https
:path = /resource
host = example.org
accept = image/jpeg
example HTTP response has only response HeaderFields
sent as HEADERS frame
followed by zero or more CONTINUATION frames
equivalence HTTP/1.1 304 Not Modified HEADERS
ETag: "xyzzy" ==> + END_STREAM
Expires: Thu, 23 Jan ... + END_HEADERS
:status = 304
etag = "xyzzy"
expires = Thu, 23 Jan ...
example HTTP POST request has HeaderFields and payload data
sent as one HEADERS frame
followed by zero or more CONTINUATION frames with request header fields
followed by one or more DATA frames
last CONTINUATION or HEADERS END_HEADERS set and
last DATA END_STREAM set
equivalence POST /resource HTTP/1.1 HEADERS
Host: example.org ==> - END_STREAM
Content-Type: image/jpeg - END_HEADERS
Content-Length: 123 :method = POST
:path = /resource
{binary data} :scheme = https
CONTINUATION
+ END_HEADERS
content-type = image/jpeg
host = example.org
content-length = 123
DATA
+ END_STREAM
{binary data}
example HTTP response has HeaderFields and payload data
sent as one HEADERS frame
followed by zero or more CONTINUATION frames
followed by one or more DATA frames
last DATA END_STREAM set
equivalence HTTP/1.1 200 OK HEADERS
Content-Type: image/jpeg ==> - END_STREAM
Content-Length: 123 + END_HEADERS
:status = 200
{binary data} content-type = image/jpeg
content-length = 123
DATA
+ END_STREAM
{binary data}
informational response 1xx status code other than 101 is sent as HEADERS frame
followed by zero or more CONTINUATION frames
trailing HeaderFields are sent as HEADERS frame with END_STREAM set
after sending request or response HeaderBlock
all DATA frames
example 100 (Continue) status code is sent for request with "100-continue" token Expect HeaderField
trailing HeaderField is sent after
equivalence HTTP/1.1 100 Continue HEADERS
Extension-Field: bar ==> - END_STREAM
+ END_HEADERS
:status = 100
extension-field = bar
HTTP/1.1 200 OK HEADERS
Content-Type: image/jpeg ==> - END_STREAM
Transfer-Encoding: chunked + END_HEADERS
Trailer: Foo :status = 200
content-length = 123
123 content-type = image/jpeg
{binary data} trailer = Foo
0
Foo: bar DATA
- END_STREAM
{binary data}
HEADERS
+ END_STREAM
+ END_HEADERS
foo = bar
ServerPush used by server by sending PUSH_PROMISE
steps unoptimized Client initiates request1
Server sends response1
Client sends request2
Server sends response2
Client sends request3
Server sends response3
optimized1 Client initiates request1
Server sends response1
PUSH_PROMISE
response2
response3
optimized2 Client initiates request1
Server sends PUSH_PROMISE
response1
response2
response3
response1 has data making Client request again
for example links to images
optimized1 PUSH_PROMISE may stop Client from sending request2 and request3
optimized2 PUSH_PROMISE stops Client from sending request2 and request3
negotiated independently for each hop between Server and Client
Request is PUSH_PROMISE Frame followed by zero or more CONTINUATION Frames
always associated with explicit request from client
sent on stream where explicit request from client happened
frames are interspersed with response frames
Response uses stream promised by PUSH_PROMISE
transmits HTTP response
client may not requests for the promised response until promised stream has closed
if client does not want or
server takes too long to begin sending
then client sends RST_STREAM with StreamIdentifier = PromisedStreamID and
either CANCEL
REFUSED_STREAM
if received by Client
then Client validates either server is authoritative
proxy is configured for corresponding request
example if server has certificate "example.com" DNS-ID or Common Name
then server is not permitted to respond for "https://www.example.org/doc"
if client accepts PUSH_PROMISE and
limits number of streams in "reserved (remote)" and
limit it reached
then client sends stream error ENHANCE_YOUR_CALM
stream begins with HEADERS changing stream into "half-closed (remote)" for server
"half-closed (local)" for client
ends with END_STREAM set changing stream into "closed"
client never sends frame with END_STREAM set
if is cacheable and RFC7234 Section 3
client implements HTTP cache
then client may store response
if "no-cache" cache response directive is present and
response stream PromisedStreamID is still open
then response is successfully validated on Server
if not cacheable then HTTP cache does not store response
may be made available to application separately
if received by intermediary
then intermediary chosses independently of actions taken by server
to forward it or not to client
to make additional pushes to client
if server receives then connection error PROTOCOL_ERROR
Cacheability is possible
depends on Cache-Control HeaderField
has issues if single server hosts multiple clients
example server offers parts of URI space
to multiple users
if clients have no authority over representations of resources
then clients cant push representations of resources
not used if server is not authoritative
CONNECT in HTTP/1.x RFC7231 Section 4.3.6
converts connection into tunnel to remote host
used with HTTP proxies to establish TLS session with origin server
to interact with "https" resources
in HTTP/2 establishes tunnel over one stream to remote host
":method" = "CONNECT"
":scheme" omitted
":path" omitted
":authority" has host and port to connect to
authority-form of request-target of CONNECT requests RFC7230 Section 5.3
if not following definition then treat as malformed
proxy steps establishes TCP connection with server in ":authority"
sends client HEADERS with 2xx series status code RFC7231 Section 4.3.6
each peer sends initial HEADERS
all subsecuent DATA frames correspond to data sent on TCP
transmits client Payload DATA to TCP server
assembles server TCP data into DATA for client
if receives DATA with END_STREAM set
then proxy sends last TCP segment with FIN set
if receives TCP segment with FIN set
then proxy sends DATA frame with END_STREAM set
if receives Frames other than DATA
RST_STREAM
WINDOW_UPDATE
PRIORITY
then sends stream error RST_STREAM
if detects TCP connection error or
receives TCP segment with RST set
then sends stream error CONNECT_ERROR
if detects HTTP/2 stream or connection error
then sends TCP segment with RST set
if close stream of peer
then TCP connection may remain in TIME_WAIT state
maintain resources
does not rely only on SETTINGS_MAX_CONCURRENT_STREAMS to limit resources consumed
may be abused to create disproportionate load on proxy
peer stream creation is less expensive than proxy TCP connection creation and maintenance
if client receives END_STREAM set
then client sends DATA with END_STREAM set
DATA frame with END_STREAM set is equivalent to TCP FIN bit
final TCP segment may be empty
final DATA frame may be empty
TCP connection may be closed by either peer
TCP connection error is signaled with RST_STREAM
Connection is persistent
Servers may maintain open for as long as possible
terminate if idle
clients may open multiple to same IP and port
using different SNI
to provide different TLS client certificates
avoid multiple with same configuration
avoid multiple to same host and port pair
derived from URI or
configured proxy or
alternative service RFC7838
not close until no further communication necessary
user navigates away from web page
server closes connection
replace Connection near exhaustion of streamidentifier
Connection with errors
to refresh TLS key
may have multiple concurrently open Streams
either endpoint interleaving Frames from multiple Streams
has HeaderCompression context
HeaderDeCompression context
if HeaderDeCompression error then send connection error COMPRESSION_ERROR
Reuse if requests have multiple different URI authority components
if origin server is authoritative
if IP addresses resolve to same host in URI and using TCP without TLS
if host in URI has valid certificate and using TCP with TLS
if origin server certificate has multiple "subjectAltName" or names with wildcards
one of which is valid for authority in URI
example server has certificate with "subjectAltName" of "*.example.com"
may Reuse Connection for requests to "https://a.example.com/" and
"https://b.example.com/"
for multiple origin servers requests may go to wrong origin server
example if middlebox uses SNI extension to select origin server and
does TLS termination
then clients may send confidential data to wrong server even when server is authoritative
if not wanted by server and
server receives request
then server sends 421 (Misdirected Request) status code
for all client requests sent via proxy
421 (Misdirected Request) Status Code
indicates that request to server has no response
may be sent by server not configured to respond to request with specific scheme and authority in URI
is not generated by proxies
cacheable by default
may be disabled by method definition or
explicit cache controls RFC7234 Section 4.2.2
if client sends request and
receives 421 Status Code
then client may retry request on different connection
usingTLS may follow general guidance RFC7525
version >= 1.2
support SNI
clients indicate target domain name
disable TLS 1.2 compression
disable TLS 1.2 renegotiation
if server wants to change to other protocol that supports renegotiation
then server sends error HTTP_1_1_REQUIRED
support key size >= 224bit for ECDHE else send connection error INADEQUATE_SECURITY
>= 2048bit for DHE else send connection error INADEQUATE_SECURITY
<= 4096bit for DHE for client
support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 with P-256
endpoint may do connection error INADEQUATE_SECURITY if ciphersuite in BlackList is negotiated
endpoint must not do connection error INADEQUATE_SECURITY if ciphersuite not in BlackList is negotiated
if client supports HTTP/1.1 and HTTP/2
then client may advertise ciphersuites in BlackList
BlackList RFC7540 Appendix A
if attacker can control confidential data transported over TLS
then do not compress confidential data
if separate compression dictionaries are not used for each source of confidential data
then do not compressed confidential data
ServerAuthority determine if server is authoritative of response
uses definition in RFC7230 Section 9.1
local name resolution for "http" URI scheme
authenticated server identity RFC2818 Section 3 for "https" scheme
Extensions are within the scope of one HTTP/2 connection
applies to protocol elements defined here
does not affect existing options for extending HTTP
may use new Frame Type or
new SETTINGS Parameter or
new ErrorCode
without prior arrangement or negotiation
implementations ignore unknown or unsupported values in all extensible protocol elements
discard frames with unknown or unsupported types
if Extension Frames appear in middle of HeaderBlock
then send connection error PROTOCOL_ERROR
if Extension changes semantics of existing protocol components
then negotiate Extension before use
for negotiating use of Extension there is no specific method
SETTINGS Parameter may be used
defaults to disabled
CrossProtocolAttack attacker makes client start transaction in one protocol toward server using different protocol
transaction valid in second protocol
avoided by using TLS handshake with ALPN identifier
may happen if not using TLS and
server ignores parts of HTTP/1.1 request with Upgrade header
client connection preface
IntermediaryEncapsulationAttack if carriage return CR ASCII 0xd or
line feed LF ASCII 0xa or
zero character NUL ASCII 0x0 are translated verbatim
then attacker may exploit them
if request or response has invalid HeaderField name
then treat as malformed
intermediary does no translation from HTTP/2 to HTTP/1.1
if request or response has invalid character in HeaderField value
then treat as malformed
valid characters are defined by "field-content" ABNF rule RFC7230 Section 3.2
Privacy observer may locate enpoint using PING response latency
fingerprinting endpoints
correlate actions of endpoints over time
handling of settings values
FlowControl managment
priorities allocation to streams
timing of reactions
reusing connections for different origins