@@ -392,6 +392,79 @@ def socket_handler(listener):
392392
393393 self .tear_down ()
394394
395+ def test_receiving_trailers_before_reading (self ):
396+ self .set_up ()
397+
398+ recv_event = threading .Event ()
399+ wait_event = threading .Event ()
400+
401+ def socket_handler (listener ):
402+ sock = listener .accept ()[0 ]
403+
404+ e = Encoder ()
405+ e .huffman_coder = HuffmanEncoder (REQUEST_CODES , REQUEST_CODES_LENGTH )
406+
407+ # We get two messages for the connection open and then a HEADERS
408+ # frame.
409+ receive_preamble (sock )
410+ sock .recv (65535 )
411+
412+ # Now, send the headers for the response.
413+ f = build_headers_frame (
414+ [(':status' , '200' ), ('content-length' , '14' )],
415+ e
416+ )
417+ f .stream_id = 1
418+ sock .send (f .serialize ())
419+
420+ # Also send a data frame.
421+ f = DataFrame (1 )
422+ f .data = b'have some data'
423+ sock .send (f .serialize ())
424+
425+ # Wait for the main thread to signal that it wants the trailers,
426+ # then delay slightly.
427+ wait_event .wait (5 )
428+ time .sleep (0.5 )
429+
430+ # Now, send a headers frame again, containing trailing headers.
431+ f = build_headers_frame ([(':res' , 'no' ), ('trailing' , 'sure' )], e )
432+ f .flags .add ('END_STREAM' )
433+ f .stream_id = 1
434+ sock .send (f .serialize ())
435+
436+ # Wait for the message from the main thread.
437+ recv_event .set ()
438+ sock .close ()
439+
440+ self ._start_server (socket_handler )
441+ conn = self .get_connection ()
442+ conn .request ('GET' , '/' )
443+ resp = conn .get_response ()
444+
445+ # Confirm the status code.
446+ assert resp .status == 200
447+
448+ # Ask for the trailers.
449+ wait_event .set ()
450+
451+ # Confirm that we got the trailing headers, and that they don't contain
452+ # reserved headers. More importantly, check the trailers *first*,
453+ # before we read from the stream.
454+ assert resp .trailers ['trailing' ] == [b'sure' ]
455+ assert resp .trailers .get (':res' ) is None
456+ assert len (resp .headers ) == 1
457+ assert len (resp .trailers ) == 1
458+
459+ # Confirm that the stream is still readable.
460+ assert resp .read () == b'have some data'
461+ assert resp ._stream ._in_window_manager .document_size == 14
462+
463+ # Awesome, we're done now.
464+ recv_event .wait (5 )
465+
466+ self .tear_down ()
467+
395468 def test_clean_shut_down (self ):
396469 self .set_up ()
397470
0 commit comments