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