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