1818 combine_repeated_headers , split_repeated_headers , h2_safe_headers
1919)
2020from hyper .common .headers import HTTPHeaderMap
21- from hyper .compat import zlib_compressobj
21+ from hyper .compat import zlib_compressobj , is_py2
2222from hyper .contrib import HTTP20Adapter
2323import hyper .http20 .errors as errors
2424import errno
2929from io import BytesIO
3030import hyper
3131
32+
3233def decode_frame (frame_data ):
3334 f , length = Frame .parse_frame_header (frame_data [:9 ])
3435 f .parse_body (memoryview (frame_data [9 :9 + length ]))
@@ -87,11 +88,11 @@ def test_putrequest_autosets_headers(self):
8788 c .putrequest ('GET' , '/' )
8889 s = c .recent_stream
8990
90- assert s .headers == [
91- (':method' , 'GET' ),
92- (':scheme' , 'https' ),
93- (':authority' , 'www.google.com' ),
94- (':path' , '/' ),
91+ assert list ( s .headers . items ()) == [
92+ (b ':method' , b 'GET' ),
93+ (b ':scheme' , b 'https' ),
94+ (b ':authority' , b 'www.google.com' ),
95+ (b ':path' , b '/' ),
9596 ]
9697
9798 def test_putheader_puts_headers (self ):
@@ -101,12 +102,29 @@ def test_putheader_puts_headers(self):
101102 c .putheader ('name' , 'value' )
102103 s = c .recent_stream
103104
104- assert s .headers == [
105- (':method' , 'GET' ),
106- (':scheme' , 'https' ),
107- (':authority' , 'www.google.com' ),
108- (':path' , '/' ),
109- ('name' , 'value' ),
105+ assert list (s .headers .items ()) == [
106+ (b':method' , b'GET' ),
107+ (b':scheme' , b'https' ),
108+ (b':authority' , b'www.google.com' ),
109+ (b':path' , b'/' ),
110+ (b'name' , b'value' ),
111+ ]
112+
113+ def test_putheader_replaces_headers (self ):
114+ c = HTTP20Connection ("www.google.com" )
115+
116+ c .putrequest ('GET' , '/' )
117+ c .putheader (':authority' , 'www.example.org' , replace = True )
118+ c .putheader ('name' , 'value' )
119+ c .putheader ('name' , 'value2' , replace = True )
120+ s = c .recent_stream
121+
122+ assert list (s .headers .items ()) == [
123+ (b':method' , b'GET' ),
124+ (b':scheme' , b'https' ),
125+ (b':path' , b'/' ),
126+ (b':authority' , b'www.example.org' ),
127+ (b'name' , b'value2' ),
110128 ]
111129
112130 def test_endheaders_sends_data (self ):
@@ -203,6 +221,33 @@ def test_putrequest_sends_data(self):
203221 assert len (sock .queue ) == 2
204222 assert c ._out_flow_control_window == 65535 - len (b'hello' )
205223
224+ def test_different_request_headers (self ):
225+ sock = DummySocket ()
226+
227+ c = HTTP20Connection ('www.google.com' )
228+ c ._sock = sock
229+ c .request ('GET' , '/' , body = 'hello' , headers = {b'name' : b'value' })
230+ s = c .recent_stream
231+
232+ assert list (s .headers .items ()) == [
233+ (b':method' , b'GET' ),
234+ (b':scheme' , b'https' ),
235+ (b':authority' , b'www.google.com' ),
236+ (b':path' , b'/' ),
237+ (b'name' , b'value' ),
238+ ]
239+
240+ c .request ('GET' , '/' , body = 'hello' , headers = {u'name2' : u'value2' })
241+ s = c .recent_stream
242+
243+ assert list (s .headers .items ()) == [
244+ (b':method' , b'GET' ),
245+ (b':scheme' , b'https' ),
246+ (b':authority' , b'www.google.com' ),
247+ (b':path' , b'/' ),
248+ (b'name2' , b'value2' ),
249+ ]
250+
206251 def test_closed_connections_are_reset (self ):
207252 c = HTTP20Connection ('www.google.com' )
208253 c ._sock = DummySocket ()
@@ -502,11 +547,11 @@ def test_that_using_proxy_keeps_http_headers_intact(self):
502547 c .request ('GET' , '/' )
503548 s = c .recent_stream
504549
505- assert s .headers == [
506- (':method' , 'GET' ),
507- (':scheme' , 'http' ),
508- (':authority' , 'www.google.com' ),
509- (':path' , '/' ),
550+ assert list ( s .headers . items ()) == [
551+ (b ':method' , b 'GET' ),
552+ (b ':scheme' , b 'http' ),
553+ (b ':authority' , b 'www.google.com' ),
554+ (b ':path' , b '/' ),
510555 ]
511556
512557 def test_recv_cb_n_times (self ):
@@ -695,13 +740,30 @@ def test_streams_have_ids(self):
695740
696741 def test_streams_initially_have_no_headers (self ):
697742 s = Stream (1 , None , None , None , None , None , None )
698- assert s .headers == []
743+ assert list ( s .headers . items ()) == []
699744
700745 def test_streams_can_have_headers (self ):
701746 s = Stream (1 , None , None , None , None , None , None )
702747 s .add_header ("name" , "value" )
703- assert s .headers == [("name" , "value" )]
748+ assert list (s .headers .items ()) == [(b"name" , b"value" )]
749+
750+ def test_streams_can_replace_headers (self ):
751+ s = Stream (1 , None , None , None , None , None , None )
752+ s .add_header ("name" , "value" )
753+ s .add_header ("name" , "other_value" , replace = True )
704754
755+ assert list (s .headers .items ()) == [(b"name" , b"other_value" )]
756+
757+ def test_streams_can_replace_none_headers (self ):
758+ s = Stream (1 , None , None , None , None , None , None )
759+ s .add_header ("name" , "value" )
760+ s .add_header ("other_name" , "other_value" , replace = True )
761+
762+ assert list (s .headers .items ()) == [
763+ (b"name" , b"value" ),
764+ (b"other_name" , b"other_value" )
765+ ]
766+
705767 def test_stream_opening_sends_headers (self ):
706768 def data_callback (frame ):
707769 assert isinstance (frame , HeadersFrame )
@@ -1465,11 +1527,23 @@ def test_connection_error_when_send_out_of_range_frame(self):
14651527 with pytest .raises (ValueError ):
14661528 c ._send_cb (d )
14671529
1530+
14681531# Some utility classes for the tests.
14691532class NullEncoder (object ):
14701533 @staticmethod
14711534 def encode (headers ):
1472- return '\n ' .join ("%s%s" % (name , val ) for name , val in headers )
1535+
1536+ def to_str (v ):
1537+ if is_py2 :
1538+ return str (v )
1539+ else :
1540+ if not isinstance (v , str ):
1541+ v = str (v , 'utf-8' )
1542+ return v
1543+
1544+ return '\n ' .join ("%s%s" % (to_str (name ), to_str (val ))
1545+ for name , val in headers )
1546+
14731547
14741548class FixedDecoder (object ):
14751549 def __init__ (self , result ):
@@ -1478,6 +1552,7 @@ def __init__(self, result):
14781552 def decode (self , headers ):
14791553 return self .result
14801554
1555+
14811556class DummySocket (object ):
14821557 def __init__ (self ):
14831558 self .queue = []
0 commit comments