@@ -134,6 +134,33 @@ def test_putheader(self):
134134 conn .putheader ('Content-length' , 42 )
135135 self .assertIn (b'Content-length: 42' , conn ._buffer )
136136
137+ conn .putheader ('Foo' , ' bar ' )
138+ self .assertIn (b'Foo: bar ' , conn ._buffer )
139+ conn .putheader ('Bar' , '\t baz\t ' )
140+ self .assertIn (b'Bar: \t baz\t ' , conn ._buffer )
141+ conn .putheader ('Authorization' , 'Bearer mytoken' )
142+ self .assertIn (b'Authorization: Bearer mytoken' , conn ._buffer )
143+ conn .putheader ('IterHeader' , 'IterA' , 'IterB' )
144+ self .assertIn (b'IterHeader: IterA\r \n \t IterB' , conn ._buffer )
145+ conn .putheader ('LatinHeader' , b'\xFF ' )
146+ self .assertIn (b'LatinHeader: \xFF ' , conn ._buffer )
147+ conn .putheader ('Utf8Header' , b'\xc3 \x80 ' )
148+ self .assertIn (b'Utf8Header: \xc3 \x80 ' , conn ._buffer )
149+ conn .putheader ('C1-Control' , b'next\x85 line' )
150+ self .assertIn (b'C1-Control: next\x85 line' , conn ._buffer )
151+ conn .putheader ('Embedded-Fold-Space' , 'is\r \n allowed' )
152+ self .assertIn (b'Embedded-Fold-Space: is\r \n allowed' , conn ._buffer )
153+ conn .putheader ('Embedded-Fold-Tab' , 'is\r \n \t allowed' )
154+ self .assertIn (b'Embedded-Fold-Tab: is\r \n \t allowed' , conn ._buffer )
155+ conn .putheader ('Key Space' , 'value' )
156+ self .assertIn (b'Key Space: value' , conn ._buffer )
157+ conn .putheader ('KeySpace ' , 'value' )
158+ self .assertIn (b'KeySpace : value' , conn ._buffer )
159+ conn .putheader (b'Nonbreak\xa0 Space' , 'value' )
160+ self .assertIn (b'Nonbreak\xa0 Space: value' , conn ._buffer )
161+ conn .putheader (b'\xa0 NonbreakSpace' , 'value' )
162+ self .assertIn (b'\xa0 NonbreakSpace: value' , conn ._buffer )
163+
137164 def test_ipv6host_header (self ):
138165 # Default host header on IPv6 transaction should wrapped by [] if
139166 # its actual IPv6 address
@@ -153,6 +180,35 @@ def test_ipv6host_header(self):
153180 conn .request ('GET' , '/foo' )
154181 self .assertTrue (sock .data .startswith (expected ))
155182
183+ def test_invalid_headers (self ):
184+ conn = client .HTTPConnection ('example.com' )
185+ conn .sock = FakeSocket ('' )
186+ conn .putrequest ('GET' , '/' )
187+
188+ # http://tools.ietf.org/html/rfc7230#section-3.2.4, whitespace is no
189+ # longer allowed in header names
190+ cases = (
191+ (b'Invalid\r \n Name' , b'ValidValue' ),
192+ (b'Invalid\r Name' , b'ValidValue' ),
193+ (b'Invalid\n Name' , b'ValidValue' ),
194+ (b'\r \n InvalidName' , b'ValidValue' ),
195+ (b'\r InvalidName' , b'ValidValue' ),
196+ (b'\n InvalidName' , b'ValidValue' ),
197+ (b' InvalidName' , b'ValidValue' ),
198+ (b'\t InvalidName' , b'ValidValue' ),
199+ (b'Invalid:Name' , b'ValidValue' ),
200+ (b':InvalidName' , b'ValidValue' ),
201+ (b'ValidName' , b'Invalid\r \n Value' ),
202+ (b'ValidName' , b'Invalid\r Value' ),
203+ (b'ValidName' , b'Invalid\n Value' ),
204+ (b'ValidName' , b'InvalidValue\r \n ' ),
205+ (b'ValidName' , b'InvalidValue\r ' ),
206+ (b'ValidName' , b'InvalidValue\n ' ),
207+ )
208+ for name , value in cases :
209+ with self .assertRaisesRegex (ValueError , 'Invalid header' ):
210+ conn .putheader (name , value )
211+
156212
157213class BasicTest (TestCase ):
158214 def test_status_lines (self ):
0 commit comments