@@ -228,23 +228,22 @@ def receive_frame(self, frame):
228228 pass
229229
230230 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.
231233 headers = self ._decoder .decode (b'' .join (self .header_data ))
232234
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.
235238 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 )
243240 else :
244241 self .promised_headers [self .promised_stream_id ] = headers
245242
243+ # We've handled the headers, zero them out.
246244 self .header_data = None
247245
246+
248247 def open (self , end ):
249248 """
250249 Open the stream. Does this by encoding and sending the headers: no more
@@ -334,6 +333,39 @@ def close(self, error_code=None):
334333 # connection.
335334 self ._close_cb (self .stream_id , error_code )
336335
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+
337369 def _send_chunk (self , data , final ):
338370 """
339371 Implements most of the sending logic.
0 commit comments