xref: /unit/test/test_http_header.py (revision 1065:f1b1e26f0e24)
1import unittest
2from unit.applications.lang.python import TestApplicationPython
3
4
5class TestHTTPHeader(TestApplicationPython):
6    prerequisites = ['python']
7
8    def test_http_header_value_leading_sp(self):
9        self.load('custom_header')
10
11        resp = self.get(
12            headers={
13                'Host': 'localhost',
14                'Custom-Header': ' ,',
15                'Connection': 'close',
16            }
17        )
18
19        self.assertEqual(resp['status'], 200, 'value leading sp status')
20        self.assertEqual(
21            resp['headers']['Custom-Header'],
22            ',',
23            'value leading sp custom header',
24        )
25
26    def test_http_header_value_leading_htab(self):
27        self.load('custom_header')
28
29        resp = self.get(
30            headers={
31                'Host': 'localhost',
32                'Custom-Header': '\t,',
33                'Connection': 'close',
34            }
35        )
36
37        self.assertEqual(resp['status'], 200, 'value leading htab status')
38        self.assertEqual(
39            resp['headers']['Custom-Header'],
40            ',',
41            'value leading htab custom header',
42        )
43
44    def test_http_header_value_trailing_sp(self):
45        self.load('custom_header')
46
47        resp = self.get(
48            headers={
49                'Host': 'localhost',
50                'Custom-Header': ', ',
51                'Connection': 'close',
52            }
53        )
54
55        self.assertEqual(resp['status'], 200, 'value trailing sp status')
56        self.assertEqual(
57            resp['headers']['Custom-Header'],
58            ',',
59            'value trailing sp custom header',
60        )
61
62    def test_http_header_value_trailing_htab(self):
63        self.load('custom_header')
64
65        resp = self.get(
66            headers={
67                'Host': 'localhost',
68                'Custom-Header': ',\t',
69                'Connection': 'close',
70            }
71        )
72
73        self.assertEqual(resp['status'], 200, 'value trailing htab status')
74        self.assertEqual(
75            resp['headers']['Custom-Header'],
76            ',',
77            'value trailing htab custom header',
78        )
79
80    def test_http_header_value_both_sp(self):
81        self.load('custom_header')
82
83        resp = self.get(
84            headers={
85                'Host': 'localhost',
86                'Custom-Header': ' , ',
87                'Connection': 'close',
88            }
89        )
90
91        self.assertEqual(resp['status'], 200, 'value both sp status')
92        self.assertEqual(
93            resp['headers']['Custom-Header'],
94            ',',
95            'value both sp custom header',
96        )
97
98    def test_http_header_value_both_htab(self):
99        self.load('custom_header')
100
101        resp = self.get(
102            headers={
103                'Host': 'localhost',
104                'Custom-Header': '\t,\t',
105                'Connection': 'close',
106            }
107        )
108
109        self.assertEqual(resp['status'], 200, 'value both htab status')
110        self.assertEqual(
111            resp['headers']['Custom-Header'],
112            ',',
113            'value both htab custom header',
114        )
115
116    def test_http_header_value_chars(self):
117        self.load('custom_header')
118
119        resp = self.get(
120            headers={
121                'Host': 'localhost',
122                'Custom-Header': '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~',
123                'Connection': 'close',
124            }
125        )
126
127        self.assertEqual(resp['status'], 200, 'value chars status')
128        self.assertEqual(
129            resp['headers']['Custom-Header'],
130            '(),/:;<=>?@[\]{}\t !#$%&\'*+-.^_`|~',
131            'value chars custom header',
132        )
133
134    def test_http_header_value_chars_edge(self):
135        self.load('custom_header')
136
137        resp = self.http(
138            b"""GET / HTTP/1.1
139Host: localhost
140Custom-Header: \x20\xFF
141Connection: close
142
143""",
144            raw=True,
145            encoding='latin1',
146        )
147
148        self.assertEqual(resp['status'], 200, 'value chars edge status')
149        self.assertEqual(
150            resp['headers']['Custom-Header'], '\xFF', 'value chars edge'
151        )
152
153    def test_http_header_value_chars_below(self):
154        self.load('custom_header')
155
156        resp = self.http(
157            b"""GET / HTTP/1.1
158Host: localhost
159Custom-Header: \x1F
160Connection: close
161
162""",
163            raw=True,
164        )
165
166        self.assertEqual(resp['status'], 400, 'value chars below')
167
168    def test_http_header_field_leading_sp(self):
169        self.load('empty')
170
171        resp = self.get(
172            headers={
173                'Host': 'localhost',
174                ' Custom-Header': 'blah',
175                'Connection': 'close',
176            }
177        )
178
179        self.assertEqual(resp['status'], 400, 'field leading sp')
180
181    def test_http_header_field_leading_htab(self):
182        self.load('empty')
183
184        resp = self.get(
185            headers={
186                'Host': 'localhost',
187                '\tCustom-Header': 'blah',
188                'Connection': 'close',
189            }
190        )
191
192        self.assertEqual(resp['status'], 400, 'field leading htab')
193
194    def test_http_header_field_trailing_sp(self):
195        self.load('empty')
196
197        resp = self.get(
198            headers={
199                'Host': 'localhost',
200                'Custom-Header ': 'blah',
201                'Connection': 'close',
202            }
203        )
204
205        self.assertEqual(resp['status'], 400, 'field trailing sp')
206
207    def test_http_header_field_trailing_htab(self):
208        self.load('empty')
209
210        resp = self.get(
211            headers={
212                'Host': 'localhost',
213                'Custom-Header\t': 'blah',
214                'Connection': 'close',
215            }
216        )
217
218        self.assertEqual(resp['status'], 400, 'field trailing htab')
219
220    def test_http_header_content_length_big(self):
221        self.load('empty')
222
223        self.assertEqual(
224            self.post(
225                headers={
226                    'Host': 'localhost',
227                    'Content-Length': str(2 ** 64),
228                    'Connection': 'close',
229                },
230                body='X' * 1000,
231            )['status'],
232            400,
233            'Content-Length big',
234        )
235
236    def test_http_header_content_length_negative(self):
237        self.load('empty')
238
239        self.assertEqual(
240            self.post(
241                headers={
242                    'Host': 'localhost',
243                    'Content-Length': '-100',
244                    'Connection': 'close',
245                },
246                body='X' * 1000,
247            )['status'],
248            400,
249            'Content-Length negative',
250        )
251
252    def test_http_header_content_length_text(self):
253        self.load('empty')
254
255        self.assertEqual(
256            self.post(
257                headers={
258                    'Host': 'localhost',
259                    'Content-Length': 'blah',
260                    'Connection': 'close',
261                },
262                body='X' * 1000,
263            )['status'],
264            400,
265            'Content-Length text',
266        )
267
268    def test_http_header_content_length_multiple_values(self):
269        self.load('empty')
270
271        self.assertEqual(
272            self.post(
273                headers={
274                    'Host': 'localhost',
275                    'Content-Length': '41, 42',
276                    'Connection': 'close',
277                },
278                body='X' * 1000,
279            )['status'],
280            400,
281            'Content-Length multiple value',
282        )
283
284    def test_http_header_content_length_multiple_fields(self):
285        self.load('empty')
286
287        self.assertEqual(
288            self.post(
289                headers={
290                    'Host': 'localhost',
291                    'Content-Length': ['41', '42'],
292                    'Connection': 'close',
293                },
294                body='X' * 1000,
295            )['status'],
296            400,
297            'Content-Length multiple fields',
298        )
299
300    @unittest.skip('not yet')
301    def test_http_header_host_absent(self):
302        self.load('host')
303
304        resp = self.get(headers={'Connection': 'close'})
305
306        self.assertEqual(resp['status'], 400, 'Host absent status')
307
308    def test_http_header_host_empty(self):
309        self.load('host')
310
311        resp = self.get(headers={'Host': '', 'Connection': 'close'})
312
313        self.assertEqual(resp['status'], 200, 'Host empty status')
314        self.assertNotEqual(
315            resp['headers']['X-Server-Name'], '', 'Host empty SERVER_NAME'
316        )
317
318    def test_http_header_host_big(self):
319        self.load('empty')
320
321        self.assertEqual(
322            self.get(headers={'Host': 'X' * 10000, 'Connection': 'close'})[
323                'status'
324            ],
325            431,
326            'Host big',
327        )
328
329    def test_http_header_host_port(self):
330        self.load('host')
331
332        resp = self.get(
333            headers={'Host': 'exmaple.com:7080', 'Connection': 'close'}
334        )
335
336        self.assertEqual(resp['status'], 200, 'Host port status')
337        self.assertEqual(
338            resp['headers']['X-Server-Name'],
339            'exmaple.com',
340            'Host port SERVER_NAME',
341        )
342        self.assertEqual(
343            resp['headers']['X-Http-Host'],
344            'exmaple.com:7080',
345            'Host port HTTP_HOST',
346        )
347
348    def test_http_header_host_port_empty(self):
349        self.load('host')
350
351        resp = self.get(
352            headers={'Host': 'exmaple.com:', 'Connection': 'close'}
353        )
354
355        self.assertEqual(resp['status'], 200, 'Host port empty status')
356        self.assertEqual(
357            resp['headers']['X-Server-Name'],
358            'exmaple.com',
359            'Host port empty SERVER_NAME',
360        )
361        self.assertEqual(
362            resp['headers']['X-Http-Host'],
363            'exmaple.com:',
364            'Host port empty HTTP_HOST',
365        )
366
367    def test_http_header_host_literal(self):
368        self.load('host')
369
370        resp = self.get(headers={'Host': '127.0.0.1', 'Connection': 'close'})
371
372        self.assertEqual(resp['status'], 200, 'Host literal status')
373        self.assertEqual(
374            resp['headers']['X-Server-Name'],
375            '127.0.0.1',
376            'Host literal SERVER_NAME',
377        )
378
379    def test_http_header_host_literal_ipv6(self):
380        self.load('host')
381
382        resp = self.get(headers={'Host': '[::1]:7080', 'Connection': 'close'})
383
384        self.assertEqual(resp['status'], 200, 'Host literal ipv6 status')
385        self.assertEqual(
386            resp['headers']['X-Server-Name'],
387            '[::1]',
388            'Host literal ipv6 SERVER_NAME',
389        )
390        self.assertEqual(
391            resp['headers']['X-Http-Host'],
392            '[::1]:7080',
393            'Host literal ipv6 HTTP_HOST',
394        )
395
396    def test_http_header_host_trailing_period(self):
397        self.load('host')
398
399        resp = self.get(headers={'Host': '127.0.0.1.', 'Connection': 'close'})
400
401        self.assertEqual(resp['status'], 200, 'Host trailing period status')
402        self.assertEqual(
403            resp['headers']['X-Server-Name'],
404            '127.0.0.1',
405            'Host trailing period SERVER_NAME',
406        )
407        self.assertEqual(
408            resp['headers']['X-Http-Host'],
409            '127.0.0.1.',
410            'Host trailing period HTTP_HOST',
411        )
412
413    def test_http_header_host_trailing_period_2(self):
414        self.load('host')
415
416        resp = self.get(
417            headers={'Host': 'EXAMPLE.COM.', 'Connection': 'close'}
418        )
419
420        self.assertEqual(resp['status'], 200, 'Host trailing period 2 status')
421        self.assertEqual(
422            resp['headers']['X-Server-Name'],
423            'example.com',
424            'Host trailing period 2 SERVER_NAME',
425        )
426        self.assertEqual(
427            resp['headers']['X-Http-Host'],
428            'EXAMPLE.COM.',
429            'Host trailing period 2 HTTP_HOST',
430        )
431
432    def test_http_header_host_case_insensitive(self):
433        self.load('host')
434
435        resp = self.get(headers={'Host': 'EXAMPLE.COM', 'Connection': 'close'})
436
437        self.assertEqual(resp['status'], 200, 'Host case insensitive')
438        self.assertEqual(
439            resp['headers']['X-Server-Name'],
440            'example.com',
441            'Host case insensitive SERVER_NAME',
442        )
443
444    def test_http_header_host_double_dot(self):
445        self.load('empty')
446
447        self.assertEqual(
448            self.get(headers={'Host': '127.0.0..1', 'Connection': 'close'})[
449                'status'
450            ],
451            400,
452            'Host double dot',
453        )
454
455    def test_http_header_host_slash(self):
456        self.load('empty')
457
458        self.assertEqual(
459            self.get(headers={'Host': '/localhost', 'Connection': 'close'})[
460                'status'
461            ],
462            400,
463            'Host slash',
464        )
465
466    def test_http_header_host_multiple_fields(self):
467        self.load('empty')
468
469        self.assertEqual(
470            self.get(
471                headers={
472                    'Host': ['localhost', 'example.com'],
473                    'Connection': 'close',
474                }
475            )['status'],
476            400,
477            'Host multiple fields',
478        )
479
480
481if __name__ == '__main__':
482    TestHTTPHeader.main()
483