You got a few things incorrectly.
A message is a combination of one or two HEADER
frames (carrying the HTTP headers), zero or more DATA frames, and one optional terminal HEADER
frame (carrying the HTTP trailers).
You can look at examples in this section of RFC 7540.
There is a special case for 100 Continue
responses, that can begin with two HEADERS
rather than one. In what follows we can ignore this case.
A DATA
frame does have a stream ID, because all frames share the frame header defined in this section of RFC 7540.
What is described in section 6.1 is only the body of the DATA
frame.
A message is a half of a HTTP/2 stream. A message represents either a HTTP request or a HTTP response.
A HTTP/2 stream is the combination of a request message and a response message.
Note that this is not to be confused with the flag_end_stream
that signals the last frame sent for that particular stream by either peer.
A typical GET
request performed by a browser will then have (assuming the stream ID is 13):
- one
HEADERS
frame with ID=13, flag_end_headers=true
and flag_end_stream=true
(a GET
request typically has no body)
A typical response to that GET
request will then have:
- one
HEADERS
frame with ID=13 and flag_end_headers=true
- one or more
DATA
frames, all with ID=13; the last DATA
frame will have flag_end_stream=true
.
Note that due to multiplexing, frames can interleave; this means that if you have two concurrent responses (say for stream 13 and stream 15), for example, you can have this sequence:
HEADERS(13) HEADERS(15) DATA(15) DATA(13) DATA(13] DATA(15) DATA(15]
where the bracket ]
means that it's the last frame in the stream.