@@ -228,23 +228,22 @@ def receive_frame(self, frame):
228
228
pass
229
229
230
230
if 'END_HEADERS' in frame .flags :
231
+ # Begin by decoding the header block. If this fails, we need to
232
+ # tear down the entire connection. TODO: actually do that.
231
233
headers = self ._decoder .decode (b'' .join (self .header_data ))
232
234
233
- # The header block may be for trailers or headers. If we've already
234
- # received headers these _must_ be for trailers.
235
+ # If we're involved in a PUSH_PROMISE sequence, this header block
236
+ # is the proposed request headers. Save it off. Otherwise, handle
237
+ # it as an in-stream HEADERS block.
235
238
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." )
239
+ self ._handle_header_block (headers )
243
240
else :
244
241
self .promised_headers [self .promised_stream_id ] = headers
245
242
243
+ # We've handled the headers, zero them out.
246
244
self .header_data = None
247
245
246
+
248
247
def open (self , end ):
249
248
"""
250
249
Open the stream. Does this by encoding and sending the headers: no more
@@ -334,6 +333,39 @@ def close(self, error_code=None):
334
333
# connection.
335
334
self ._close_cb (self .stream_id , error_code )
336
335
336
+ def _handle_header_block (self , headers ):
337
+ """
338
+ Handles the logic for receiving a completed headers block.
339
+
340
+ A headers block is an uninterrupted sequence of one HEADERS frame
341
+ followed by zero or more CONTINUATION frames, and is terminated by a
342
+ frame bearing the END_HEADERS flag.
343
+
344
+ HTTP/2 allows receipt of up to three such blocks on a stream. The first
345
+ is optional, and contains a 1XX response. The second is mandatory, and
346
+ must contain a final response (200 or higher). The third is optional,
347
+ and may contain 'trailers', headers that are sent after a chunk-encoded
348
+ body is sent. This method enforces the logic associated with this,
349
+ storing the headers in the appropriate places.
350
+ """
351
+
352
+ # At this stage we should check for a provisional response (1XX). As
353
+ # hyper doesn't currently support such responses, we'll leave that as a
354
+ # TODO.
355
+ # TODO: Handle 1XX responses here.
356
+
357
+ # The header block may be for trailers or headers. If we've already
358
+ # received headers these _must_ be for trailers.
359
+ if self .response_headers is None :
360
+ self .response_headers = headers
361
+ elif self .response_trailers is None :
362
+ self .response_trailers = headers
363
+ else :
364
+ # Received too many headers blocks.
365
+ raise ProtocolError ("Too many header blocks." )
366
+
367
+ self .header_data = None
368
+
337
369
def _send_chunk (self , data , final ):
338
370
"""
339
371
Implements most of the sending logic.
0 commit comments