@@ -148,6 +148,33 @@ def test_putheader(self):
148
148
conn .putheader ('Content-length' , 42 )
149
149
self .assertIn (b'Content-length: 42' , conn ._buffer )
150
150
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
+
151
178
def test_ipv6host_header (self ):
152
179
# Default host header on IPv6 transaction should wrapped by [] if
153
180
# its actual IPv6 address
@@ -177,6 +204,36 @@ def test_malformed_headers_coped_with(self):
177
204
self .assertEqual (resp .getheader ('First' ), 'val' )
178
205
self .assertEqual (resp .getheader ('Second' ), 'val' )
179
206
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
+
180
237
181
238
class BasicTest (TestCase ):
182
239
def test_status_lines (self ):
0 commit comments