|
13 | 13 | Each stream is identified by a monotonically increasing integer, assigned to
|
14 | 14 | the stream by the endpoint that initiated the stream.
|
15 | 15 | """
|
| 16 | +from .exceptions import ProtocolError |
16 | 17 | from .frame import (
|
17 | 18 | FRAME_MAX_LEN, FRAMES, HeadersFrame, DataFrame, PushPromiseFrame,
|
18 | 19 | WindowUpdateFrame, ContinuationFrame, BlockedFrame
|
@@ -65,6 +66,10 @@ def __init__(self,
|
65 | 66 | # HEADERS..CONTINUATION frame sequence finishes.
|
66 | 67 | self.response_headers = None
|
67 | 68 |
|
| 69 | + # Set to a key-value set of the response trailers once their |
| 70 | + # HEADERS..CONTINUATION frame sequence finishes. |
| 71 | + self.response_trailers = None |
| 72 | + |
68 | 73 | # A dict mapping the promised stream ID of a pushed resource to a
|
69 | 74 | # key-value set of its request headers. Entries are added once their
|
70 | 75 | # PUSH_PROMISE..CONTINUATION frame sequence finishes.
|
@@ -224,8 +229,17 @@ def receive_frame(self, frame):
|
224 | 229 |
|
225 | 230 | if 'END_HEADERS' in frame.flags:
|
226 | 231 | headers = self._decoder.decode(b''.join(self.header_data))
|
227 |
| - if self.promised_stream_id is None: |
228 |
| - self.response_headers = headers |
| 232 | + |
| 233 | + # The header block may be for trailers or headers. If we've already |
| 234 | + # received headers these _must_ be for trailers. |
| 235 | + if (self.promised_stream_id is None): |
| 236 | + if self.response_headers is None: |
| 237 | + self.response_headers = headers |
| 238 | + elif self.response_trailers is None: |
| 239 | + self.response_trailers = headers |
| 240 | + else: |
| 241 | + # Received too many headers blocks. |
| 242 | + raise ProtocolError("Too many header blocks.") |
229 | 243 | else:
|
230 | 244 | self.promised_headers[self.promised_stream_id] = headers
|
231 | 245 |
|
|
0 commit comments