@@ -148,6 +148,33 @@ def test_putheader(self):
148148 conn .putheader ('Content-length' , 42 )
149149 self .assertIn (b'Content-length: 42' , conn ._buffer )
150150
151+ conn .putheader ('Foo' , ' bar ' )
152+ self .assertIn (b'Foo: bar ' , conn ._buffer )
153+ conn .putheader ('Bar' , '\t baz\t ' )
154+ self .assertIn (b'Bar: \t baz\t ' , conn ._buffer )
155+ conn .putheader ('Authorization' , 'Bearer mytoken' )
156+ self .assertIn (b'Authorization: Bearer mytoken' , conn ._buffer )
157+ conn .putheader ('IterHeader' , 'IterA' , 'IterB' )
158+ self .assertIn (b'IterHeader: IterA\r \n \t IterB' , conn ._buffer )
159+ conn .putheader ('LatinHeader' , b'\xFF ' )
160+ self .assertIn (b'LatinHeader: \xFF ' , conn ._buffer )
161+ conn .putheader ('Utf8Header' , b'\xc3 \x80 ' )
162+ self .assertIn (b'Utf8Header: \xc3 \x80 ' , conn ._buffer )
163+ conn .putheader ('C1-Control' , b'next\x85 line' )
164+ self .assertIn (b'C1-Control: next\x85 line' , conn ._buffer )
165+ conn .putheader ('Embedded-Fold-Space' , 'is\r \n allowed' )
166+ self .assertIn (b'Embedded-Fold-Space: is\r \n allowed' , conn ._buffer )
167+ conn .putheader ('Embedded-Fold-Tab' , 'is\r \n \t allowed' )
168+ self .assertIn (b'Embedded-Fold-Tab: is\r \n \t allowed' , conn ._buffer )
169+ conn .putheader ('Key Space' , 'value' )
170+ self .assertIn (b'Key Space: value' , conn ._buffer )
171+ conn .putheader ('KeySpace ' , 'value' )
172+ self .assertIn (b'KeySpace : value' , conn ._buffer )
173+ conn .putheader (b'Nonbreak\xa0 Space' , 'value' )
174+ self .assertIn (b'Nonbreak\xa0 Space: value' , conn ._buffer )
175+ conn .putheader (b'\xa0 NonbreakSpace' , 'value' )
176+ self .assertIn (b'\xa0 NonbreakSpace: value' , conn ._buffer )
177+
151178 def test_ipv6host_header (self ):
152179 # Default host header on IPv6 transaction should wrapped by [] if
153180 # its actual IPv6 address
@@ -177,6 +204,36 @@ def test_malformed_headers_coped_with(self):
177204 self .assertEqual (resp .getheader ('First' ), 'val' )
178205 self .assertEqual (resp .getheader ('Second' ), 'val' )
179206
207+ def test_invalid_headers (self ):
208+ conn = client .HTTPConnection ('example.com' )
209+ conn .sock = FakeSocket ('' )
210+ conn .putrequest ('GET' , '/' )
211+
212+ # http://tools.ietf.org/html/rfc7230#section-3.2.4, whitespace is no
213+ # longer allowed in header names
214+ cases = (
215+ (b'Invalid\r \n Name' , b'ValidValue' ),
216+ (b'Invalid\r Name' , b'ValidValue' ),
217+ (b'Invalid\n Name' , b'ValidValue' ),
218+ (b'\r \n InvalidName' , b'ValidValue' ),
219+ (b'\r InvalidName' , b'ValidValue' ),
220+ (b'\n InvalidName' , b'ValidValue' ),
221+ (b' InvalidName' , b'ValidValue' ),
222+ (b'\t InvalidName' , b'ValidValue' ),
223+ (b'Invalid:Name' , b'ValidValue' ),
224+ (b':InvalidName' , b'ValidValue' ),
225+ (b'ValidName' , b'Invalid\r \n Value' ),
226+ (b'ValidName' , b'Invalid\r Value' ),
227+ (b'ValidName' , b'Invalid\n Value' ),
228+ (b'ValidName' , b'InvalidValue\r \n ' ),
229+ (b'ValidName' , b'InvalidValue\r ' ),
230+ (b'ValidName' , b'InvalidValue\n ' ),
231+ )
232+ for name , value in cases :
233+ with self .subTest ((name , value )):
234+ with self .assertRaisesRegex (ValueError , 'Invalid header' ):
235+ conn .putheader (name , value )
236+
180237
181238class BasicTest (TestCase ):
182239 def test_status_lines (self ):
0 commit comments