1# -*- coding: utf-8 -*- 2import pytest 3from unit.applications.lang.python import TestApplicationPython 4from unit.option import option 5 6 7class TestRouting(TestApplicationPython): 8 prerequisites = {'modules': {'python': 'any'}} 9 10 def setup_method(self): 11 assert 'success' in self.conf( 12 { 13 "listeners": {"*:7080": {"pass": "routes"}}, 14 "routes": [ 15 { 16 "match": {"method": "GET"}, 17 "action": {"return": 200}, 18 } 19 ], 20 "applications": {}, 21 } 22 ), 'routing configure' 23 24 def route(self, route): 25 return self.conf([route], 'routes') 26 27 def route_match(self, match): 28 assert 'success' in self.route( 29 {"match": match, "action": {"return": 200}} 30 ), 'route match configure' 31 32 def route_match_invalid(self, match): 33 assert 'error' in self.route( 34 {"match": match, "action": {"return": 200}} 35 ), 'route match configure invalid' 36 37 def host(self, host, status): 38 assert ( 39 self.get(headers={'Host': host, 'Connection': 'close'})['status'] 40 == status 41 ), 'match host' 42 43 def cookie(self, cookie, status): 44 assert ( 45 self.get( 46 headers={ 47 'Host': 'localhost', 48 'Cookie': cookie, 49 'Connection': 'close', 50 }, 51 )['status'] 52 == status 53 ), 'match cookie' 54 55 def test_routes_match_method_positive(self): 56 assert self.get()['status'] == 200, 'GET' 57 assert self.post()['status'] == 404, 'POST' 58 59 def test_routes_match_method_positive_many(self): 60 self.route_match({"method": ["GET", "POST"]}) 61 62 assert self.get()['status'] == 200, 'GET' 63 assert self.post()['status'] == 200, 'POST' 64 assert self.delete()['status'] == 404, 'DELETE' 65 66 def test_routes_match_method_negative(self): 67 self.route_match({"method": "!GET"}) 68 69 assert self.get()['status'] == 404, 'GET' 70 assert self.post()['status'] == 200, 'POST' 71 72 def test_routes_match_method_negative_many(self): 73 self.route_match({"method": ["!GET", "!POST"]}) 74 75 assert self.get()['status'] == 404, 'GET' 76 assert self.post()['status'] == 404, 'POST' 77 assert self.delete()['status'] == 200, 'DELETE' 78 79 def test_routes_match_method_wildcard_left(self): 80 self.route_match({"method": "*ET"}) 81 82 assert self.get()['status'] == 200, 'GET' 83 assert self.post()['status'] == 404, 'POST' 84 85 def test_routes_match_method_wildcard_right(self): 86 self.route_match({"method": "GE*"}) 87 88 assert self.get()['status'] == 200, 'GET' 89 assert self.post()['status'] == 404, 'POST' 90 91 def test_routes_match_method_wildcard_left_right(self): 92 self.route_match({"method": "*GET*"}) 93 94 assert self.get()['status'] == 200, 'GET' 95 assert self.post()['status'] == 404, 'POST' 96 97 def test_routes_match_method_wildcard(self): 98 self.route_match({"method": "*"}) 99 100 assert self.get()['status'] == 200, 'GET' 101 102 def test_routes_match_invalid(self): 103 self.route_match_invalid({"method": "**"}) 104 105 def test_routes_match_valid(self): 106 self.route_match({"method": "blah*"}) 107 self.route_match({"host": "*blah*blah"}) 108 self.route_match({"host": "blah*blah*blah"}) 109 self.route_match({"host": "blah*blah*"}) 110 111 def test_routes_match_empty_exact(self): 112 self.route_match({"uri": ""}) 113 assert self.get()['status'] == 404 114 115 self.route_match({"uri": "/"}) 116 assert self.get()['status'] == 200 117 assert self.get(url='/blah')['status'] == 404 118 119 def test_routes_match_negative(self): 120 self.route_match({"uri": "!"}) 121 assert self.get()['status'] == 200 122 123 self.route_match({"uri": "!*"}) 124 assert self.get()['status'] == 404 125 126 self.route_match({"uri": "!/"}) 127 assert self.get()['status'] == 404 128 assert self.get(url='/blah')['status'] == 200 129 130 self.route_match({"uri": "!*blah"}) 131 assert self.get()['status'] == 200 132 assert self.get(url='/bla')['status'] == 200 133 assert self.get(url='/blah')['status'] == 404 134 assert self.get(url='/blah1')['status'] == 200 135 136 self.route_match({"uri": "!/blah*1*"}) 137 assert self.get()['status'] == 200 138 assert self.get(url='/blah')['status'] == 200 139 assert self.get(url='/blah1')['status'] == 404 140 assert self.get(url='/blah12')['status'] == 404 141 assert self.get(url='/blah2')['status'] == 200 142 143 def test_routes_match_wildcard_middle(self): 144 self.route_match({"host": "ex*le"}) 145 146 self.host('example', 200) 147 self.host('www.example', 404) 148 self.host('example.com', 404) 149 self.host('exampl', 404) 150 151 def test_routes_match_method_case_insensitive(self): 152 self.route_match({"method": "get"}) 153 154 assert self.get()['status'] == 200, 'GET' 155 156 def test_routes_match_wildcard_left_case_insensitive(self): 157 self.route_match({"method": "*get"}) 158 assert self.get()['status'] == 200, 'GET' 159 160 self.route_match({"method": "*et"}) 161 assert self.get()['status'] == 200, 'GET' 162 163 def test_routes_match_wildcard_middle_case_insensitive(self): 164 self.route_match({"method": "g*t"}) 165 166 assert self.get()['status'] == 200, 'GET' 167 168 def test_routes_match_wildcard_right_case_insensitive(self): 169 self.route_match({"method": "get*"}) 170 assert self.get()['status'] == 200, 'GET' 171 172 self.route_match({"method": "ge*"}) 173 assert self.get()['status'] == 200, 'GET' 174 175 def test_routes_match_wildcard_substring_case_insensitive(self): 176 self.route_match({"method": "*et*"}) 177 178 assert self.get()['status'] == 200, 'GET' 179 180 def test_routes_match_wildcard_left_case_sensitive(self): 181 self.route_match({"uri": "*blah"}) 182 183 assert self.get(url='/blah')['status'] == 200, '/blah' 184 assert self.get(url='/BLAH')['status'] == 404, '/BLAH' 185 186 def test_routes_match_wildcard_middle_case_sensitive(self): 187 self.route_match({"uri": "/b*h"}) 188 189 assert self.get(url='/blah')['status'] == 200, '/blah' 190 assert self.get(url='/BLAH')['status'] == 404, '/BLAH' 191 192 def test_route_match_wildcards_ordered(self): 193 self.route_match({"uri": "/a*x*y*"}) 194 195 assert self.get(url='/axy')['status'] == 200, '/axy' 196 assert self.get(url='/ayx')['status'] == 404, '/ayx' 197 198 def test_route_match_wildcards_adjust_start(self): 199 self.route_match({"uri": "/bla*bla*"}) 200 201 assert self.get(url='/bla_foo')['status'] == 404, '/bla_foo' 202 203 def test_route_match_wildcards_adjust_start_substr(self): 204 self.route_match({"uri": "*bla*bla*"}) 205 206 assert self.get(url='/bla_foo')['status'] == 404, '/bla_foo' 207 208 def test_route_match_wildcards_adjust_end(self): 209 self.route_match({"uri": "/bla*bla"}) 210 211 assert self.get(url='/foo_bla')['status'] == 404, '/foo_bla' 212 213 def test_routes_match_wildcard_right_case_sensitive(self): 214 self.route_match({"uri": "/bla*"}) 215 216 assert self.get(url='/blah')['status'] == 200, '/blah' 217 assert self.get(url='/BLAH')['status'] == 404, '/BLAH' 218 219 def test_routes_match_wildcard_substring_case_sensitive(self): 220 self.route_match({"uri": "*bla*"}) 221 222 assert self.get(url='/blah')['status'] == 200, '/blah' 223 assert self.get(url='/BLAH')['status'] == 404, '/BLAH' 224 225 def test_routes_match_many_wildcard_substrings_case_sensitive(self): 226 self.route_match({"uri": "*a*B*c*"}) 227 228 assert self.get(url='/blah-a-B-c-blah')['status'] == 200 229 assert self.get(url='/a-B-c')['status'] == 200 230 assert self.get(url='/aBc')['status'] == 200 231 assert self.get(url='/aBCaBbc')['status'] == 200 232 assert self.get(url='/ABc')['status'] == 404 233 234 def test_routes_empty_regex(self): 235 if not option.available['modules']['regex']: 236 pytest.skip('requires regex') 237 238 self.route_match({"uri": "~"}) 239 assert self.get(url='/')['status'] == 200, 'empty regexp' 240 assert self.get(url='/anything')['status'] == 200, '/anything' 241 242 self.route_match({"uri": "!~"}) 243 assert self.get(url='/')['status'] == 404, 'empty regexp 2' 244 assert self.get(url='/nothing')['status'] == 404, '/nothing' 245 246 def test_routes_bad_regex(self): 247 if not option.available['modules']['regex']: 248 pytest.skip('requires regex') 249 250 assert 'error' in self.route( 251 {"match": {"uri": "~/bl[ah"}, "action": {"return": 200}} 252 ), 'bad regex' 253 254 status = self.route( 255 {"match": {"uri": "~(?R)?z"}, "action": {"return": 200}} 256 ) 257 if 'error' not in status: 258 assert self.get(url='/nothing_z')['status'] == 500, '/nothing_z' 259 260 status = self.route( 261 {"match": {"uri": "~((?1)?z)"}, "action": {"return": 200}} 262 ) 263 if 'error' not in status: 264 assert self.get(url='/nothing_z')['status'] == 500, '/nothing_z' 265 266 def test_routes_match_regex_case_sensitive(self): 267 if not option.available['modules']['regex']: 268 pytest.skip('requires regex') 269 270 self.route_match({"uri": "~/bl[ah]"}) 271 272 assert self.get(url='/rlah')['status'] == 404, '/rlah' 273 assert self.get(url='/blah')['status'] == 200, '/blah' 274 assert self.get(url='/blh')['status'] == 200, '/blh' 275 assert self.get(url='/BLAH')['status'] == 404, '/BLAH' 276 277 def test_routes_match_regex_negative_case_sensitive(self): 278 if not option.available['modules']['regex']: 279 pytest.skip('requires regex') 280 281 self.route_match({"uri": "!~/bl[ah]"}) 282 283 assert self.get(url='/rlah')['status'] == 200, '/rlah' 284 assert self.get(url='/blah')['status'] == 404, '/blah' 285 assert self.get(url='/blh')['status'] == 404, '/blh' 286 assert self.get(url='/BLAH')['status'] == 200, '/BLAH' 287 288 def test_routes_pass_encode(self): 289 def check_pass(path, name): 290 assert 'success' in self.conf( 291 { 292 "listeners": {"*:7080": {"pass": "applications/" + path}}, 293 "applications": { 294 name: { 295 "type": self.get_application_type(), 296 "processes": {"spare": 0}, 297 "path": option.test_dir + '/python/empty', 298 "working_directory": option.test_dir 299 + '/python/empty', 300 "module": "wsgi", 301 } 302 }, 303 } 304 ) 305 306 assert self.get()['status'] == 200 307 308 check_pass("%25", "%") 309 check_pass("blah%2Fblah", "blah/blah") 310 check_pass("%2Fblah%2F%2Fblah%2F", "/blah//blah/") 311 check_pass("%20blah%252Fblah%7E", " blah%2Fblah~") 312 313 def check_pass_error(path, name): 314 assert 'error' in self.conf( 315 { 316 "listeners": {"*:7080": {"pass": "applications/" + path}}, 317 "applications": { 318 name: { 319 "type": self.get_application_type(), 320 "processes": {"spare": 0}, 321 "path": option.test_dir + '/python/empty', 322 "working_directory": option.test_dir 323 + '/python/empty', 324 "module": "wsgi", 325 } 326 }, 327 } 328 ) 329 330 check_pass_error("%", "%") 331 check_pass_error("%1", "%1") 332 333 def test_routes_absent(self): 334 assert 'success' in self.conf( 335 { 336 "listeners": {"*:7081": {"pass": "applications/empty"}}, 337 "applications": { 338 "empty": { 339 "type": self.get_application_type(), 340 "processes": {"spare": 0}, 341 "path": option.test_dir + '/python/empty', 342 "working_directory": option.test_dir + '/python/empty', 343 "module": "wsgi", 344 } 345 }, 346 } 347 ) 348 349 assert self.get(port=7081)['status'] == 200, 'routes absent' 350 351 def test_routes_pass_invalid(self): 352 assert 'error' in self.conf( 353 {"pass": "routes/blah"}, 'listeners/*:7080' 354 ), 'routes invalid' 355 356 def test_route_empty(self): 357 assert 'success' in self.conf( 358 { 359 "listeners": {"*:7080": {"pass": "routes/main"}}, 360 "routes": {"main": []}, 361 "applications": {}, 362 } 363 ), 'route empty configure' 364 365 assert self.get()['status'] == 404, 'route empty' 366 367 def test_routes_route_empty(self): 368 assert 'success' in self.conf( 369 {}, 'listeners' 370 ), 'routes empty listeners configure' 371 372 assert 'success' in self.conf({}, 'routes'), 'routes empty configure' 373 374 def test_routes_route_match_absent(self): 375 assert 'success' in self.conf( 376 [{"action": {"return": 200}}], 'routes' 377 ), 'route match absent configure' 378 379 assert self.get()['status'] == 200, 'route match absent' 380 381 def test_routes_route_action_absent(self, skip_alert): 382 skip_alert(r'failed to apply new conf') 383 384 assert 'error' in self.conf( 385 [{"match": {"method": "GET"}}], 'routes' 386 ), 'route pass absent configure' 387 388 def test_routes_route_pass(self): 389 assert 'success' in self.conf( 390 { 391 "applications": { 392 "app": { 393 "type": self.get_application_type(), 394 "processes": {"spare": 0}, 395 "path": "/app", 396 "module": "wsgi", 397 } 398 }, 399 "upstreams": { 400 "one": { 401 "servers": { 402 "127.0.0.1:7081": {}, 403 "127.0.0.1:7082": {}, 404 }, 405 }, 406 "two": { 407 "servers": { 408 "127.0.0.1:7081": {}, 409 "127.0.0.1:7082": {}, 410 }, 411 }, 412 }, 413 } 414 ) 415 416 assert 'success' in self.conf( 417 [{"action": {"pass": "routes"}}], 'routes' 418 ) 419 assert 'success' in self.conf( 420 [{"action": {"pass": "applications/app"}}], 'routes' 421 ) 422 assert 'success' in self.conf( 423 [{"action": {"pass": "upstreams/one"}}], 'routes' 424 ) 425 426 def test_routes_route_pass_absent(self): 427 assert 'error' in self.conf( 428 [{"match": {"method": "GET"}, "action": {}}], 'routes' 429 ), 'route pass absent configure' 430 431 def test_routes_route_pass_invalid(self): 432 assert 'success' in self.conf( 433 { 434 "applications": { 435 "app": { 436 "type": self.get_application_type(), 437 "processes": {"spare": 0}, 438 "path": "/app", 439 "module": "wsgi", 440 } 441 }, 442 "upstreams": { 443 "one": { 444 "servers": { 445 "127.0.0.1:7081": {}, 446 "127.0.0.1:7082": {}, 447 }, 448 }, 449 "two": { 450 "servers": { 451 "127.0.0.1:7081": {}, 452 "127.0.0.1:7082": {}, 453 }, 454 }, 455 }, 456 } 457 ) 458 459 assert 'error' in self.conf( 460 [{"action": {"pass": "blah"}}], 'routes' 461 ), 'route pass invalid' 462 assert 'error' in self.conf( 463 [{"action": {"pass": "routes/blah"}}], 'routes' 464 ), 'route pass routes invalid' 465 assert 'error' in self.conf( 466 [{"action": {"pass": "applications/blah"}}], 'routes' 467 ), 'route pass applications invalid' 468 assert 'error' in self.conf( 469 [{"action": {"pass": "upstreams/blah"}}], 'routes' 470 ), 'route pass upstreams invalid' 471 472 def test_routes_action_unique(self, temp_dir): 473 assert 'success' in self.conf( 474 { 475 "listeners": { 476 "*:7080": {"pass": "routes"}, 477 "*:7081": {"pass": "applications/app"}, 478 }, 479 "routes": [{"action": {"proxy": "http://127.0.0.1:7081"}}], 480 "applications": { 481 "app": { 482 "type": self.get_application_type(), 483 "processes": {"spare": 0}, 484 "path": "/app", 485 "module": "wsgi", 486 } 487 }, 488 } 489 ) 490 491 assert 'error' in self.conf( 492 {"proxy": "http://127.0.0.1:7081", "share": temp_dir}, 493 'routes/0/action', 494 ), 'proxy share' 495 assert 'error' in self.conf( 496 { 497 "proxy": "http://127.0.0.1:7081", 498 "pass": "applications/app", 499 }, 500 'routes/0/action', 501 ), 'proxy pass' 502 assert 'error' in self.conf( 503 {"share": temp_dir, "pass": "applications/app"}, 504 'routes/0/action', 505 ), 'share pass' 506 507 def test_routes_rules_two(self): 508 assert 'success' in self.conf( 509 [ 510 {"match": {"method": "GET"}, "action": {"return": 200}}, 511 {"match": {"method": "POST"}, "action": {"return": 201}}, 512 ], 513 'routes', 514 ), 'rules two configure' 515 516 assert self.get()['status'] == 200, 'rules two match first' 517 assert self.post()['status'] == 201, 'rules two match second' 518 519 def test_routes_two(self): 520 assert 'success' in self.conf( 521 { 522 "listeners": {"*:7080": {"pass": "routes/first"}}, 523 "routes": { 524 "first": [ 525 { 526 "match": {"method": "GET"}, 527 "action": {"pass": "routes/second"}, 528 } 529 ], 530 "second": [ 531 { 532 "match": {"host": "localhost"}, 533 "action": {"return": 200}, 534 } 535 ], 536 }, 537 "applications": {}, 538 } 539 ), 'routes two configure' 540 541 assert self.get()['status'] == 200, 'routes two' 542 543 def test_routes_match_host_positive(self): 544 self.route_match({"host": "localhost"}) 545 546 assert self.get()['status'] == 200, 'localhost' 547 self.host('localhost.', 200) 548 self.host('localhost.', 200) 549 self.host('.localhost', 404) 550 self.host('www.localhost', 404) 551 self.host('localhost1', 404) 552 553 @pytest.mark.skip('not yet') 554 def test_routes_match_host_absent(self): 555 self.route_match({"host": "localhost"}) 556 557 assert ( 558 self.get(headers={'Connection': 'close'})['status'] == 400 559 ), 'match host absent' 560 561 def test_routes_match_host_ipv4(self): 562 self.route_match({"host": "127.0.0.1"}) 563 564 self.host('127.0.0.1', 200) 565 self.host('127.0.0.1:7080', 200) 566 567 def test_routes_match_host_ipv6(self): 568 self.route_match({"host": "[::1]"}) 569 570 self.host('[::1]', 200) 571 self.host('[::1]:7080', 200) 572 573 def test_routes_match_host_positive_many(self): 574 self.route_match({"host": ["localhost", "example.com"]}) 575 576 assert self.get()['status'] == 200, 'localhost' 577 self.host('example.com', 200) 578 579 def test_routes_match_host_positive_and_negative(self): 580 self.route_match({"host": ["*example.com", "!www.example.com"]}) 581 582 assert self.get()['status'] == 404, 'localhost' 583 self.host('example.com', 200) 584 self.host('www.example.com', 404) 585 self.host('!www.example.com', 200) 586 587 def test_routes_match_host_positive_and_negative_wildcard(self): 588 self.route_match({"host": ["*example*", "!www.example*"]}) 589 590 self.host('example.com', 200) 591 self.host('www.example.com', 404) 592 593 def test_routes_match_host_case_insensitive(self): 594 self.route_match({"host": "Example.com"}) 595 596 self.host('example.com', 200) 597 self.host('EXAMPLE.COM', 200) 598 599 def test_routes_match_host_port(self): 600 self.route_match({"host": "example.com"}) 601 602 self.host('example.com:7080', 200) 603 604 def test_routes_match_host_empty(self): 605 self.route_match({"host": ""}) 606 607 self.host('', 200) 608 assert ( 609 self.get(http_10=True, headers={})['status'] == 200 610 ), 'match host empty 2' 611 assert self.get()['status'] == 404, 'match host empty 3' 612 613 def test_routes_match_uri_positive(self): 614 self.route_match({"uri": ["/blah", "/slash/"]}) 615 616 assert self.get()['status'] == 404, '/' 617 assert self.get(url='/blah')['status'] == 200, '/blah' 618 assert self.get(url='/blah#foo')['status'] == 200, '/blah#foo' 619 assert self.get(url='/blah?var')['status'] == 200, '/blah?var' 620 assert self.get(url='//blah')['status'] == 200, '//blah' 621 assert self.get(url='/slash/foo/../')['status'] == 200, 'relative' 622 assert self.get(url='/slash/./')['status'] == 200, '/slash/./' 623 assert self.get(url='/slash//.//')['status'] == 200, 'adjacent slashes' 624 assert self.get(url='/%')['status'] == 400, 'percent' 625 assert self.get(url='/%1')['status'] == 400, 'percent digit' 626 assert self.get(url='/%A')['status'] == 400, 'percent letter' 627 assert self.get(url='/slash/.?args')['status'] == 200, 'dot args' 628 assert self.get(url='/slash/.#frag')['status'] == 200, 'dot frag' 629 assert ( 630 self.get(url='/slash/foo/..?args')['status'] == 200 631 ), 'dot dot args' 632 assert ( 633 self.get(url='/slash/foo/..#frag')['status'] == 200 634 ), 'dot dot frag' 635 assert self.get(url='/slash/.')['status'] == 200, 'trailing dot' 636 assert ( 637 self.get(url='/slash/foo/..')['status'] == 200 638 ), 'trailing dot dot' 639 640 def test_routes_match_uri_case_sensitive(self): 641 self.route_match({"uri": "/BLAH"}) 642 643 assert self.get(url='/blah')['status'] == 404, '/blah' 644 assert self.get(url='/BlaH')['status'] == 404, '/BlaH' 645 assert self.get(url='/BLAH')['status'] == 200, '/BLAH' 646 647 def test_routes_match_uri_normalize(self): 648 self.route_match({"uri": "/blah"}) 649 650 assert self.get(url='/%62%6c%61%68')['status'] == 200, 'normalize' 651 652 def test_routes_match_empty_array(self): 653 self.route_match({"uri": []}) 654 655 assert self.get(url='/blah')['status'] == 200, 'empty array' 656 657 def test_routes_reconfigure(self): 658 assert 'success' in self.conf([], 'routes'), 'redefine' 659 assert self.get()['status'] == 404, 'redefine request' 660 661 assert 'success' in self.conf( 662 [{"action": {"return": 200}}], 'routes' 663 ), 'redefine 2' 664 assert self.get()['status'] == 200, 'redefine request 2' 665 666 assert 'success' in self.conf([], 'routes'), 'redefine 3' 667 assert self.get()['status'] == 404, 'redefine request 3' 668 669 assert 'success' in self.conf( 670 { 671 "listeners": {"*:7080": {"pass": "routes/main"}}, 672 "routes": {"main": [{"action": {"return": 200}}]}, 673 "applications": {}, 674 } 675 ), 'redefine 4' 676 assert self.get()['status'] == 200, 'redefine request 4' 677 678 assert 'success' in self.conf_delete('routes/main/0'), 'redefine 5' 679 assert self.get()['status'] == 404, 'redefine request 5' 680 681 assert 'success' in self.conf_post( 682 {"action": {"return": 200}}, 'routes/main' 683 ), 'redefine 6' 684 assert self.get()['status'] == 200, 'redefine request 6' 685 686 assert 'error' in self.conf( 687 {"action": {"return": 200}}, 'routes/main/2' 688 ), 'redefine 7' 689 assert 'success' in self.conf( 690 {"action": {"return": 201}}, 'routes/main/1' 691 ), 'redefine 8' 692 693 assert len(self.conf_get('routes/main')) == 2, 'redefine conf 8' 694 assert self.get()['status'] == 200, 'redefine request 8' 695 696 def test_routes_edit(self): 697 self.route_match({"method": "GET"}) 698 699 assert self.get()['status'] == 200, 'routes edit GET' 700 assert self.post()['status'] == 404, 'routes edit POST' 701 702 assert 'success' in self.conf_post( 703 {"match": {"method": "POST"}, "action": {"return": 200}}, 704 'routes', 705 ), 'routes edit configure 2' 706 assert 'GET' == self.conf_get( 707 'routes/0/match/method' 708 ), 'routes edit configure 2 check' 709 assert 'POST' == self.conf_get( 710 'routes/1/match/method' 711 ), 'routes edit configure 2 check 2' 712 713 assert self.get()['status'] == 200, 'routes edit GET 2' 714 assert self.post()['status'] == 200, 'routes edit POST 2' 715 716 assert 'success' in self.conf_delete( 717 'routes/0' 718 ), 'routes edit configure 3' 719 720 assert self.get()['status'] == 404, 'routes edit GET 3' 721 assert self.post()['status'] == 200, 'routes edit POST 3' 722 723 assert 'error' in self.conf_delete( 724 'routes/1' 725 ), 'routes edit configure invalid' 726 assert 'error' in self.conf_delete( 727 'routes/-1' 728 ), 'routes edit configure invalid 2' 729 assert 'error' in self.conf_delete( 730 'routes/blah' 731 ), 'routes edit configure invalid 3' 732 733 assert self.get()['status'] == 404, 'routes edit GET 4' 734 assert self.post()['status'] == 200, 'routes edit POST 4' 735 736 assert 'success' in self.conf_delete( 737 'routes/0' 738 ), 'routes edit configure 5' 739 740 assert self.get()['status'] == 404, 'routes edit GET 5' 741 assert self.post()['status'] == 404, 'routes edit POST 5' 742 743 assert 'success' in self.conf_post( 744 {"match": {"method": "POST"}, "action": {"return": 200}}, 745 'routes', 746 ), 'routes edit configure 6' 747 748 assert self.get()['status'] == 404, 'routes edit GET 6' 749 assert self.post()['status'] == 200, 'routes edit POST 6' 750 751 assert 'success' in self.conf( 752 { 753 "listeners": {"*:7080": {"pass": "routes/main"}}, 754 "routes": {"main": [{"action": {"return": 200}}]}, 755 "applications": {}, 756 } 757 ), 'route edit configure 7' 758 759 assert 'error' in self.conf_delete( 760 'routes/0' 761 ), 'routes edit configure invalid 4' 762 assert 'error' in self.conf_delete( 763 'routes/main' 764 ), 'routes edit configure invalid 5' 765 766 assert self.get()['status'] == 200, 'routes edit GET 7' 767 768 assert 'success' in self.conf_delete( 769 'listeners/*:7080' 770 ), 'route edit configure 8' 771 assert 'success' in self.conf_delete( 772 'routes/main' 773 ), 'route edit configure 9' 774 775 def test_match_edit(self, skip_alert): 776 skip_alert(r'failed to apply new conf') 777 778 self.route_match({"method": ["GET", "POST"]}) 779 780 assert self.get()['status'] == 200, 'match edit GET' 781 assert self.post()['status'] == 200, 'match edit POST' 782 assert self.put()['status'] == 404, 'match edit PUT' 783 784 assert 'success' in self.conf_post( 785 '\"PUT\"', 'routes/0/match/method' 786 ), 'match edit configure 2' 787 assert ['GET', 'POST', 'PUT'] == self.conf_get( 788 'routes/0/match/method' 789 ), 'match edit configure 2 check' 790 791 assert self.get()['status'] == 200, 'match edit GET 2' 792 assert self.post()['status'] == 200, 'match edit POST 2' 793 assert self.put()['status'] == 200, 'match edit PUT 2' 794 795 assert 'success' in self.conf_delete( 796 'routes/0/match/method/1' 797 ), 'match edit configure 3' 798 assert ['GET', 'PUT'] == self.conf_get( 799 'routes/0/match/method' 800 ), 'match edit configure 3 check' 801 802 assert self.get()['status'] == 200, 'match edit GET 3' 803 assert self.post()['status'] == 404, 'match edit POST 3' 804 assert self.put()['status'] == 200, 'match edit PUT 3' 805 806 assert 'success' in self.conf_delete( 807 'routes/0/match/method/1' 808 ), 'match edit configure 4' 809 assert ['GET'] == self.conf_get( 810 'routes/0/match/method' 811 ), 'match edit configure 4 check' 812 813 assert self.get()['status'] == 200, 'match edit GET 4' 814 assert self.post()['status'] == 404, 'match edit POST 4' 815 assert self.put()['status'] == 404, 'match edit PUT 4' 816 817 assert 'error' in self.conf_delete( 818 'routes/0/match/method/1' 819 ), 'match edit configure invalid' 820 assert 'error' in self.conf_delete( 821 'routes/0/match/method/-1' 822 ), 'match edit configure invalid 2' 823 assert 'error' in self.conf_delete( 824 'routes/0/match/method/blah' 825 ), 'match edit configure invalid 3' 826 assert ['GET'] == self.conf_get( 827 'routes/0/match/method' 828 ), 'match edit configure 5 check' 829 830 assert self.get()['status'] == 200, 'match edit GET 5' 831 assert self.post()['status'] == 404, 'match edit POST 5' 832 assert self.put()['status'] == 404, 'match edit PUT 5' 833 834 assert 'success' in self.conf_delete( 835 'routes/0/match/method/0' 836 ), 'match edit configure 6' 837 assert [] == self.conf_get( 838 'routes/0/match/method' 839 ), 'match edit configure 6 check' 840 841 assert self.get()['status'] == 200, 'match edit GET 6' 842 assert self.post()['status'] == 200, 'match edit POST 6' 843 assert self.put()['status'] == 200, 'match edit PUT 6' 844 845 assert 'success' in self.conf( 846 '"GET"', 'routes/0/match/method' 847 ), 'match edit configure 7' 848 849 assert self.get()['status'] == 200, 'match edit GET 7' 850 assert self.post()['status'] == 404, 'match edit POST 7' 851 assert self.put()['status'] == 404, 'match edit PUT 7' 852 853 assert 'error' in self.conf_delete( 854 'routes/0/match/method/0' 855 ), 'match edit configure invalid 5' 856 assert 'error' in self.conf( 857 {}, 'routes/0/action' 858 ), 'match edit configure invalid 6' 859 860 assert 'success' in self.conf( 861 {}, 'routes/0/match' 862 ), 'match edit configure 8' 863 864 assert self.get()['status'] == 200, 'match edit GET 8' 865 866 def test_routes_match_rules(self): 867 self.route_match({"method": "GET", "host": "localhost", "uri": "/"}) 868 869 assert self.get()['status'] == 200, 'routes match rules' 870 871 def test_routes_loop(self): 872 assert 'success' in self.route( 873 {"match": {"uri": "/"}, "action": {"pass": "routes"}} 874 ), 'routes loop configure' 875 876 assert self.get()['status'] == 500, 'routes loop' 877 878 def test_routes_match_headers(self): 879 self.route_match({"headers": {"host": "localhost"}}) 880 881 assert self.get()['status'] == 200, 'match headers' 882 self.host('Localhost', 200) 883 self.host('localhost.com', 404) 884 self.host('llocalhost', 404) 885 self.host('host', 404) 886 887 def test_routes_match_headers_multiple(self): 888 self.route_match({"headers": {"host": "localhost", "x-blah": "test"}}) 889 890 assert self.get()['status'] == 404, 'match headers multiple' 891 assert ( 892 self.get( 893 headers={ 894 "Host": "localhost", 895 "X-blah": "test", 896 "Connection": "close", 897 } 898 )['status'] 899 == 200 900 ), 'match headers multiple 2' 901 902 assert ( 903 self.get( 904 headers={ 905 "Host": "localhost", 906 "X-blah": "", 907 "Connection": "close", 908 } 909 )['status'] 910 == 404 911 ), 'match headers multiple 3' 912 913 def test_routes_match_headers_multiple_values(self): 914 self.route_match({"headers": {"x-blah": "test"}}) 915 916 assert ( 917 self.get( 918 headers={ 919 "Host": "localhost", 920 "X-blah": ["test", "test", "test"], 921 "Connection": "close", 922 } 923 )['status'] 924 == 200 925 ), 'match headers multiple values' 926 assert ( 927 self.get( 928 headers={ 929 "Host": "localhost", 930 "X-blah": ["test", "blah", "test"], 931 "Connection": "close", 932 } 933 )['status'] 934 == 404 935 ), 'match headers multiple values 2' 936 assert ( 937 self.get( 938 headers={ 939 "Host": "localhost", 940 "X-blah": ["test", "", "test"], 941 "Connection": "close", 942 } 943 )['status'] 944 == 404 945 ), 'match headers multiple values 3' 946 947 def test_routes_match_headers_multiple_rules(self): 948 self.route_match({"headers": {"x-blah": ["test", "blah"]}}) 949 950 assert self.get()['status'] == 404, 'match headers multiple rules' 951 assert ( 952 self.get( 953 headers={ 954 "Host": "localhost", 955 "X-blah": "test", 956 "Connection": "close", 957 } 958 )['status'] 959 == 200 960 ), 'match headers multiple rules 2' 961 assert ( 962 self.get( 963 headers={ 964 "Host": "localhost", 965 "X-blah": "blah", 966 "Connection": "close", 967 } 968 )['status'] 969 == 200 970 ), 'match headers multiple rules 3' 971 assert ( 972 self.get( 973 headers={ 974 "Host": "localhost", 975 "X-blah": ["test", "blah", "test"], 976 "Connection": "close", 977 } 978 )['status'] 979 == 200 980 ), 'match headers multiple rules 4' 981 982 assert ( 983 self.get( 984 headers={ 985 "Host": "localhost", 986 "X-blah": ["blah", ""], 987 "Connection": "close", 988 } 989 )['status'] 990 == 404 991 ), 'match headers multiple rules 5' 992 993 def test_routes_match_headers_case_insensitive(self): 994 self.route_match({"headers": {"X-BLAH": "TEST"}}) 995 996 assert ( 997 self.get( 998 headers={ 999 "Host": "localhost", 1000 "x-blah": "test", 1001 "Connection": "close", 1002 } 1003 )['status'] 1004 == 200 1005 ), 'match headers case insensitive' 1006 1007 def test_routes_match_headers_invalid(self): 1008 self.route_match_invalid({"headers": ["blah"]}) 1009 self.route_match_invalid({"headers": {"foo": ["bar", {}]}}) 1010 self.route_match_invalid({"headers": {"": "blah"}}) 1011 1012 def test_routes_match_headers_empty_rule(self): 1013 self.route_match({"headers": {"host": ""}}) 1014 1015 assert self.get()['status'] == 404, 'localhost' 1016 self.host('', 200) 1017 1018 def test_routes_match_headers_empty(self): 1019 self.route_match({"headers": {}}) 1020 assert self.get()['status'] == 200, 'empty' 1021 1022 self.route_match({"headers": []}) 1023 assert self.get()['status'] == 200, 'empty 2' 1024 1025 def test_routes_match_headers_rule_array_empty(self): 1026 self.route_match({"headers": {"blah": []}}) 1027 1028 assert self.get()['status'] == 404, 'array empty' 1029 assert ( 1030 self.get( 1031 headers={ 1032 "Host": "localhost", 1033 "blah": "foo", 1034 "Connection": "close", 1035 } 1036 )['status'] 1037 == 200 1038 ), 'match headers rule array empty 2' 1039 1040 def test_routes_match_headers_array(self): 1041 self.route_match( 1042 { 1043 "headers": [ 1044 {"x-header1": "foo*"}, 1045 {"x-header2": "bar"}, 1046 {"x-header3": ["foo", "bar"]}, 1047 {"x-header1": "bar", "x-header4": "foo"}, 1048 ] 1049 } 1050 ) 1051 1052 def check_headers(hds): 1053 hds = dict({"Host": "localhost", "Connection": "close"}, **hds) 1054 assert self.get(headers=hds)['status'] == 200, 'headers array match' 1055 1056 def check_headers_404(hds): 1057 hds = dict({"Host": "localhost", "Connection": "close"}, **hds) 1058 assert ( 1059 self.get(headers=hds)['status'] == 404 1060 ), 'headers array no match' 1061 1062 assert self.get()['status'] == 404, 'match headers array' 1063 check_headers({"x-header1": "foo123"}) 1064 check_headers({"x-header2": "bar"}) 1065 check_headers({"x-header3": "bar"}) 1066 check_headers_404({"x-header1": "bar"}) 1067 check_headers({"x-header1": "bar", "x-header4": "foo"}) 1068 1069 assert 'success' in self.conf_delete( 1070 'routes/0/match/headers/1' 1071 ), 'match headers array configure 2' 1072 1073 check_headers_404({"x-header2": "bar"}) 1074 check_headers({"x-header3": "foo"}) 1075 1076 def test_routes_match_arguments(self): 1077 self.route_match({"arguments": {"foo": "bar"}}) 1078 1079 assert self.get()['status'] == 404, 'args' 1080 assert self.get(url='/?foo=bar')['status'] == 200, 'args 2' 1081 assert self.get(url='/?foo=bar1')['status'] == 404, 'args 3' 1082 assert self.get(url='/?1foo=bar')['status'] == 404, 'args 4' 1083 assert self.get(url='/?Foo=bar')['status'] == 404, 'case' 1084 assert self.get(url='/?foo=Bar')['status'] == 404, 'case 2' 1085 1086 def test_routes_match_arguments_chars(self): 1087 chars = ( 1088 " !\"%23$%25%26'()*%2B,-./0123456789:;<%3D>?@" 1089 "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 1090 ) 1091 1092 chars_enc = "" 1093 for h1 in ["2", "3", "4", "5", "6", "7"]: 1094 for h2 in [ 1095 "0", 1096 "1", 1097 "2", 1098 "3", 1099 "4", 1100 "5", 1101 "6", 1102 "7", 1103 "8", 1104 "9", 1105 "A", 1106 "B", 1107 "C", 1108 "D", 1109 "E", 1110 "F", 1111 ]: 1112 chars_enc += "%" + h1 + h2 1113 chars_enc = chars_enc[:-3] 1114 1115 def check_args(args, query): 1116 self.route_match({"arguments": args}) 1117 assert self.get(url='/?' + query)['status'] == 200 1118 1119 check_args({chars: chars}, chars + '=' + chars) 1120 check_args({chars: chars}, chars + '=' + chars_enc) 1121 check_args({chars: chars}, chars_enc + '=' + chars) 1122 check_args({chars: chars}, chars_enc + '=' + chars_enc) 1123 check_args({chars_enc: chars_enc}, chars + '=' + chars) 1124 check_args({chars_enc: chars_enc}, chars + '=' + chars_enc) 1125 check_args({chars_enc: chars_enc}, chars_enc + '=' + chars) 1126 check_args({chars_enc: chars_enc}, chars_enc + '=' + chars_enc) 1127 1128 def test_routes_match_arguments_empty(self): 1129 self.route_match({"arguments": {}}) 1130 assert self.get()['status'] == 200, 'arguments empty' 1131 1132 self.route_match({"arguments": []}) 1133 assert self.get()['status'] == 200, 'arguments empty 2' 1134 1135 def test_routes_match_arguments_space(self): 1136 self.route_match({"arguments": {"+fo o%20": "%20b+a r"}}) 1137 assert self.get(url='/? fo o = b a r&')['status'] == 200 1138 assert self.get(url='/?+fo+o+=+b+a+r&')['status'] == 200 1139 assert self.get(url='/?%20fo%20o%20=%20b%20a%20r&')['status'] == 200 1140 1141 self.route_match({"arguments": {"%20foo": " bar"}}) 1142 assert self.get(url='/? foo= bar')['status'] == 200 1143 assert self.get(url='/?+foo=+bar')['status'] == 200 1144 assert self.get(url='/?%20foo=%20bar')['status'] == 200 1145 assert self.get(url='/?+foo= bar')['status'] == 200 1146 assert self.get(url='/?%20foo=+bar')['status'] == 200 1147 1148 def test_routes_match_arguments_equal(self): 1149 self.route_match({"arguments": {"=": "="}}) 1150 assert self.get(url='/?%3D=%3D')['status'] == 200 1151 assert self.get(url='/?%3D==')['status'] == 200 1152 assert self.get(url='/?===')['status'] == 404 1153 assert self.get(url='/?%3D%3D%3D')['status'] == 404 1154 assert self.get(url='/?==%3D')['status'] == 404 1155 1156 def test_routes_match_arguments_enc(self): 1157 self.route_match({"arguments": {"Ю": "н"}}) 1158 assert self.get(url='/?%D0%AE=%D0%BD')['status'] == 200 1159 assert self.get(url='/?%d0%ae=%d0%Bd')['status'] == 200 1160 1161 def test_routes_match_arguments_hash(self): 1162 self.route_match({"arguments": {"#": "#"}}) 1163 assert self.get(url='/?%23=%23')['status'] == 200 1164 assert self.get(url='/?%23=%23#')['status'] == 200 1165 assert self.get(url='/?#=#')['status'] == 404 1166 assert self.get(url='/?%23=#')['status'] == 404 1167 1168 def test_routes_match_arguments_wildcard(self): 1169 self.route_match({"arguments": {"foo": "*"}}) 1170 assert self.get(url='/?foo')['status'] == 200 1171 assert self.get(url='/?foo=')['status'] == 200 1172 assert self.get(url='/?foo=blah')['status'] == 200 1173 assert self.get(url='/?blah=foo')['status'] == 404 1174 1175 self.route_match({"arguments": {"foo": "%25*"}}) 1176 assert self.get(url='/?foo=%xx')['status'] == 200 1177 1178 self.route_match({"arguments": {"foo": "%2A*"}}) 1179 assert self.get(url='/?foo=*xx')['status'] == 200 1180 assert self.get(url='/?foo=xx')['status'] == 404 1181 1182 self.route_match({"arguments": {"foo": "*%2A"}}) 1183 assert self.get(url='/?foo=xx*')['status'] == 200 1184 assert self.get(url='/?foo=xx*x')['status'] == 404 1185 1186 self.route_match({"arguments": {"foo": "1*2"}}) 1187 assert self.get(url='/?foo=12')['status'] == 200 1188 assert self.get(url='/?foo=1blah2')['status'] == 200 1189 assert self.get(url='/?foo=1%2A2')['status'] == 200 1190 assert self.get(url='/?foo=x12')['status'] == 404 1191 1192 self.route_match({"arguments": {"foo": "bar*", "%25": "%25"}}) 1193 assert self.get(url='/?foo=barxx&%=%')['status'] == 200 1194 assert self.get(url='/?foo=barxx&x%=%')['status'] == 404 1195 1196 def test_routes_match_arguments_negative(self): 1197 self.route_match({"arguments": {"foo": "!"}}) 1198 assert self.get(url='/?bar')['status'] == 404 1199 assert self.get(url='/?foo')['status'] == 404 1200 assert self.get(url='/?foo=')['status'] == 404 1201 assert self.get(url='/?foo=%25')['status'] == 200 1202 1203 self.route_match({"arguments": {"foo": "!*"}}) 1204 assert self.get(url='/?bar')['status'] == 404 1205 assert self.get(url='/?foo')['status'] == 404 1206 assert self.get(url='/?foo=')['status'] == 404 1207 assert self.get(url='/?foo=blah')['status'] == 404 1208 1209 self.route_match({"arguments": {"foo": "!%25"}}) 1210 assert self.get(url='/?foo=blah')['status'] == 200 1211 assert self.get(url='/?foo=%')['status'] == 404 1212 1213 self.route_match({"arguments": {"foo": "%21blah"}}) 1214 assert self.get(url='/?foo=%21blah')['status'] == 200 1215 assert self.get(url='/?foo=!blah')['status'] == 200 1216 assert self.get(url='/?foo=bar')['status'] == 404 1217 1218 self.route_match({"arguments": {"foo": "!!%21*a"}}) 1219 assert self.get(url='/?foo=blah')['status'] == 200 1220 assert self.get(url='/?foo=!blah')['status'] == 200 1221 assert self.get(url='/?foo=!!a')['status'] == 404 1222 assert self.get(url='/?foo=!!bla')['status'] == 404 1223 1224 def test_routes_match_arguments_percent(self): 1225 self.route_match({"arguments": {"%25": "%25"}}) 1226 assert self.get(url='/?%=%')['status'] == 200 1227 assert self.get(url='/?%25=%25')['status'] == 200 1228 assert self.get(url='/?%25=%')['status'] == 200 1229 1230 self.route_match({"arguments": {"%251": "%252"}}) 1231 assert self.get(url='/?%1=%2')['status'] == 200 1232 assert self.get(url='/?%251=%252')['status'] == 200 1233 assert self.get(url='/?%251=%2')['status'] == 200 1234 1235 self.route_match({"arguments": {"%25%21%251": "%25%24%252"}}) 1236 assert self.get(url='/?%!%1=%$%2')['status'] == 200 1237 assert self.get(url='/?%25!%251=%25$%252')['status'] == 200 1238 assert self.get(url='/?%25!%1=%$%2')['status'] == 200 1239 1240 def test_routes_match_arguments_ampersand(self): 1241 self.route_match({"arguments": {"foo": "&"}}) 1242 assert self.get(url='/?foo=%26')['status'] == 200 1243 assert self.get(url='/?foo=%26&')['status'] == 200 1244 assert self.get(url='/?foo=%26%26')['status'] == 404 1245 assert self.get(url='/?foo=&')['status'] == 404 1246 1247 self.route_match({"arguments": {"&": ""}}) 1248 assert self.get(url='/?%26=')['status'] == 200 1249 assert self.get(url='/?%26=&')['status'] == 200 1250 assert self.get(url='/?%26=%26')['status'] == 404 1251 assert self.get(url='/?&=')['status'] == 404 1252 1253 def test_routes_match_arguments_complex(self): 1254 self.route_match({"arguments": {"foo": ""}}) 1255 1256 assert self.get(url='/?foo')['status'] == 200, 'complex' 1257 assert self.get(url='/?blah=blah&foo=')['status'] == 200, 'complex 2' 1258 assert self.get(url='/?&&&foo&&&')['status'] == 200, 'complex 3' 1259 assert self.get(url='/?foo&foo=bar&foo')['status'] == 404, 'complex 4' 1260 assert self.get(url='/?foo=&foo')['status'] == 200, 'complex 5' 1261 assert self.get(url='/?&=&foo&==&')['status'] == 200, 'complex 6' 1262 assert self.get(url='/?&=&bar&==&')['status'] == 404, 'complex 7' 1263 1264 def test_routes_match_arguments_multiple(self): 1265 self.route_match({"arguments": {"foo": "bar", "blah": "test"}}) 1266 1267 assert self.get()['status'] == 404, 'multiple' 1268 assert ( 1269 self.get(url='/?foo=bar&blah=test')['status'] == 200 1270 ), 'multiple 2' 1271 assert self.get(url='/?foo=bar&blah')['status'] == 404, 'multiple 3' 1272 assert self.get(url='/?foo=bar&blah=tes')['status'] == 404, 'multiple 4' 1273 assert ( 1274 self.get(url='/?foo=b%61r&bl%61h=t%65st')['status'] == 200 1275 ), 'multiple 5' 1276 1277 def test_routes_match_arguments_multiple_rules(self): 1278 self.route_match({"arguments": {"foo": ["bar", "blah"]}}) 1279 1280 assert self.get()['status'] == 404, 'rules' 1281 assert self.get(url='/?foo=bar')['status'] == 200, 'rules 2' 1282 assert self.get(url='/?foo=blah')['status'] == 200, 'rules 3' 1283 assert ( 1284 self.get(url='/?foo=blah&foo=bar&foo=blah')['status'] == 200 1285 ), 'rules 4' 1286 assert ( 1287 self.get(url='/?foo=blah&foo=bar&foo=')['status'] == 404 1288 ), 'rules 5' 1289 1290 def test_routes_match_arguments_array(self): 1291 self.route_match( 1292 { 1293 "arguments": [ 1294 {"var1": "val1*"}, 1295 {"var2": "val2"}, 1296 {"var3": ["foo", "bar"]}, 1297 {"var1": "bar", "var4": "foo"}, 1298 ] 1299 } 1300 ) 1301 1302 assert self.get()['status'] == 404, 'arr' 1303 assert self.get(url='/?var1=val123')['status'] == 200, 'arr 2' 1304 assert self.get(url='/?var2=val2')['status'] == 200, 'arr 3' 1305 assert self.get(url='/?var3=bar')['status'] == 200, 'arr 4' 1306 assert self.get(url='/?var1=bar')['status'] == 404, 'arr 5' 1307 assert self.get(url='/?var1=bar&var4=foo')['status'] == 200, 'arr 6' 1308 1309 assert 'success' in self.conf_delete( 1310 'routes/0/match/arguments/1' 1311 ), 'match arguments array configure 2' 1312 1313 assert self.get(url='/?var2=val2')['status'] == 404, 'arr 7' 1314 assert self.get(url='/?var3=foo')['status'] == 200, 'arr 8' 1315 1316 def test_routes_match_arguments_invalid(self): 1317 self.route_match_invalid({"arguments": ["var"]}) 1318 self.route_match_invalid({"arguments": [{"var1": {}}]}) 1319 self.route_match_invalid({"arguments": {"": "bar"}}) 1320 self.route_match_invalid({"arguments": {"foo": "%"}}) 1321 self.route_match_invalid({"arguments": {"foo": "%1G"}}) 1322 self.route_match_invalid({"arguments": {"%": "bar"}}) 1323 self.route_match_invalid({"arguments": {"foo": "%0"}}) 1324 self.route_match_invalid({"arguments": {"foo": "%%1F"}}) 1325 self.route_match_invalid({"arguments": {"%%1F": ""}}) 1326 self.route_match_invalid({"arguments": {"%7%F": ""}}) 1327 1328 def test_routes_match_query(self): 1329 self.route_match({"query": "!"}) 1330 assert self.get(url='/')['status'] == 404 1331 assert self.get(url='/?')['status'] == 404 1332 assert self.get(url='/?foo')['status'] == 200 1333 assert self.get(url='/?foo=')['status'] == 200 1334 assert self.get(url='/?foo=baz')['status'] == 200 1335 1336 self.route_match({"query": "foo=%26"}) 1337 assert self.get(url='/?foo=&')['status'] == 200 1338 1339 self.route_match({"query": "a=b&c=d"}) 1340 assert self.get(url='/?a=b&c=d')['status'] == 200 1341 1342 self.route_match({"query": "a=b%26c%3Dd"}) 1343 assert self.get(url='/?a=b%26c%3Dd')['status'] == 200 1344 assert self.get(url='/?a=b&c=d')['status'] == 200 1345 1346 self.route_match({"query": "a=b%26c%3Dd+e"}) 1347 assert self.get(url='/?a=b&c=d e')['status'] == 200 1348 1349 def test_routes_match_query_array(self): 1350 self.route_match({"query": ["foo", "bar"]}) 1351 1352 assert self.get()['status'] == 404, 'no args' 1353 assert self.get(url='/?foo')['status'] == 200, 'arg first' 1354 assert self.get(url='/?bar')['status'] == 200, 'arg second' 1355 1356 assert 'success' in self.conf_delete( 1357 'routes/0/match/query/1' 1358 ), 'query array remove second' 1359 1360 assert self.get(url='/?foo')['status'] == 200, 'still arg first' 1361 assert self.get(url='/?bar')['status'] == 404, 'no arg second' 1362 1363 self.route_match({"query": ["!f", "foo"]}) 1364 1365 assert self.get(url='/?f')['status'] == 404, 'negative arg' 1366 assert self.get(url='/?fo')['status'] == 404, 'negative arg 2' 1367 assert self.get(url='/?foo')['status'] == 200, 'negative arg 3' 1368 1369 self.route_match({"query": []}) 1370 assert self.get()['status'] == 200, 'empty array' 1371 1372 def test_routes_match_query_invalid(self): 1373 self.route_match_invalid({"query": [1]}) 1374 self.route_match_invalid({"query": "%"}) 1375 self.route_match_invalid({"query": "%1G"}) 1376 self.route_match_invalid({"query": "%0"}) 1377 self.route_match_invalid({"query": "%%1F"}) 1378 self.route_match_invalid({"query": ["foo", "%3D", "%%1F"]}) 1379 1380 def test_routes_match_cookies(self): 1381 self.route_match({"cookies": {"foO": "bar"}}) 1382 1383 assert self.get()['status'] == 404, 'cookie' 1384 self.cookie('foO=bar', 200) 1385 self.cookie('foO=bar;1', 200) 1386 self.cookie(['foO=bar', 'blah=blah'], 200) 1387 self.cookie('foO=bar; blah=blah', 200) 1388 self.cookie('Foo=bar', 404) 1389 self.cookie('foO=Bar', 404) 1390 self.cookie('foO=bar1', 404) 1391 self.cookie('1foO=bar;', 404) 1392 1393 def test_routes_match_cookies_empty(self): 1394 self.route_match({"cookies": {}}) 1395 assert self.get()['status'] == 200, 'cookies empty' 1396 1397 self.route_match({"cookies": []}) 1398 assert self.get()['status'] == 200, 'cookies empty 2' 1399 1400 def test_routes_match_cookies_invalid(self): 1401 self.route_match_invalid({"cookies": ["var"]}) 1402 self.route_match_invalid({"cookies": [{"foo": {}}]}) 1403 1404 def test_routes_match_cookies_complex(self): 1405 self.route_match({"cookies": {"foo": "bar=baz"}}) 1406 self.cookie('foo=bar=baz', 200) 1407 self.cookie(' foo=bar=baz ', 200) 1408 self.cookie('=foo=bar=baz', 404) 1409 1410 self.route_match({"cookies": {"foo": ""}}) 1411 self.cookie('foo=', 200) 1412 self.cookie('foo=;', 200) 1413 self.cookie(' foo=;', 200) 1414 self.cookie('foo', 404) 1415 self.cookie('', 404) 1416 self.cookie('=', 404) 1417 1418 def test_routes_match_cookies_multiple(self): 1419 self.route_match({"cookies": {"foo": "bar", "blah": "blah"}}) 1420 1421 assert self.get()['status'] == 404, 'multiple' 1422 self.cookie('foo=bar; blah=blah', 200) 1423 self.cookie(['foo=bar', 'blah=blah'], 200) 1424 self.cookie(['foo=bar; blah', 'blah'], 404) 1425 self.cookie(['foo=bar; blah=test', 'blah=blah'], 404) 1426 1427 def test_routes_match_cookies_multiple_values(self): 1428 self.route_match({"cookies": {"blah": "blah"}}) 1429 1430 self.cookie(['blah=blah', 'blah=blah', 'blah=blah'], 200) 1431 self.cookie(['blah=blah', 'blah=test', 'blah=blah'], 404) 1432 self.cookie(['blah=blah; blah=', 'blah=blah'], 404) 1433 1434 def test_routes_match_cookies_multiple_rules(self): 1435 self.route_match({"cookies": {"blah": ["test", "blah"]}}) 1436 1437 assert self.get()['status'] == 404, 'multiple rules' 1438 self.cookie('blah=test', 200) 1439 self.cookie('blah=blah', 200) 1440 self.cookie(['blah=blah', 'blah=test', 'blah=blah'], 200) 1441 self.cookie(['blah=blah; blah=test', 'blah=blah'], 200) 1442 self.cookie(['blah=blah', 'blah'], 200) # invalid cookie 1443 1444 def test_routes_match_cookies_array(self): 1445 self.route_match( 1446 { 1447 "cookies": [ 1448 {"var1": "val1*"}, 1449 {"var2": "val2"}, 1450 {"var3": ["foo", "bar"]}, 1451 {"var1": "bar", "var4": "foo"}, 1452 ] 1453 } 1454 ) 1455 1456 assert self.get()['status'] == 404, 'cookies array' 1457 self.cookie('var1=val123', 200) 1458 self.cookie('var2=val2', 200) 1459 self.cookie(' var2=val2 ', 200) 1460 self.cookie('var3=bar', 200) 1461 self.cookie('var3=bar;', 200) 1462 self.cookie('var1=bar', 404) 1463 self.cookie('var1=bar; var4=foo;', 200) 1464 self.cookie(['var1=bar', 'var4=foo'], 200) 1465 1466 assert 'success' in self.conf_delete( 1467 'routes/0/match/cookies/1' 1468 ), 'match cookies array configure 2' 1469 1470 self.cookie('var2=val2', 404) 1471 self.cookie('var3=foo', 200) 1472 1473 def test_routes_match_scheme(self): 1474 self.route_match({"scheme": "http"}) 1475 self.route_match({"scheme": "https"}) 1476 self.route_match({"scheme": "HtTp"}) 1477 self.route_match({"scheme": "HtTpS"}) 1478 1479 def test_routes_match_scheme_invalid(self): 1480 self.route_match_invalid({"scheme": ["http"]}) 1481 self.route_match_invalid({"scheme": "ftp"}) 1482 self.route_match_invalid({"scheme": "ws"}) 1483 self.route_match_invalid({"scheme": "*"}) 1484 self.route_match_invalid({"scheme": ""}) 1485 1486 def test_routes_source_port(self): 1487 def sock_port(): 1488 _, sock = self.http(b'', start=True, raw=True, no_recv=True) 1489 port = sock.getsockname()[1] 1490 return (sock, port) 1491 1492 sock, port = sock_port() 1493 sock2, port2 = sock_port() 1494 1495 self.route_match({"source": "127.0.0.1:" + str(port)}) 1496 assert self.get(sock=sock)['status'] == 200, 'exact' 1497 assert self.get(sock=sock2)['status'] == 404, 'exact 2' 1498 1499 sock, port = sock_port() 1500 sock2, port2 = sock_port() 1501 1502 self.route_match({"source": "!127.0.0.1:" + str(port)}) 1503 assert self.get(sock=sock)['status'] == 404, 'negative' 1504 assert self.get(sock=sock2)['status'] == 200, 'negative 2' 1505 1506 sock, port = sock_port() 1507 sock2, port2 = sock_port() 1508 1509 self.route_match({"source": ["*:" + str(port), "!127.0.0.1"]}) 1510 assert self.get(sock=sock)['status'] == 404, 'negative 3' 1511 assert self.get(sock=sock2)['status'] == 404, 'negative 4' 1512 1513 sock, port = sock_port() 1514 sock2, port2 = sock_port() 1515 1516 self.route_match({"source": "127.0.0.1:" + str(port) + "-" + str(port)}) 1517 assert self.get(sock=sock)['status'] == 200, 'range single' 1518 assert self.get(sock=sock2)['status'] == 404, 'range single 2' 1519 1520 socks = [ 1521 sock_port(), 1522 sock_port(), 1523 sock_port(), 1524 sock_port(), 1525 sock_port(), 1526 ] 1527 socks.sort(key=lambda sock: sock[1]) 1528 1529 self.route_match( 1530 { 1531 "source": "127.0.0.1:" 1532 + str(socks[1][1]) # second port number 1533 + "-" 1534 + str(socks[3][1]) # fourth port number 1535 } 1536 ) 1537 assert self.get(sock=socks[0][0])['status'] == 404, 'range' 1538 assert self.get(sock=socks[1][0])['status'] == 200, 'range 2' 1539 assert self.get(sock=socks[2][0])['status'] == 200, 'range 3' 1540 assert self.get(sock=socks[3][0])['status'] == 200, 'range 4' 1541 assert self.get(sock=socks[4][0])['status'] == 404, 'range 5' 1542 1543 socks = [ 1544 sock_port(), 1545 sock_port(), 1546 sock_port(), 1547 ] 1548 socks.sort(key=lambda sock: sock[1]) 1549 1550 self.route_match( 1551 { 1552 "source": [ 1553 "127.0.0.1:" + str(socks[0][1]), 1554 "127.0.0.1:" + str(socks[2][1]), 1555 ] 1556 } 1557 ) 1558 assert self.get(sock=socks[0][0])['status'] == 200, 'array' 1559 assert self.get(sock=socks[1][0])['status'] == 404, 'array 2' 1560 assert self.get(sock=socks[2][0])['status'] == 200, 'array 3' 1561 1562 def test_routes_source_addr(self): 1563 assert 'success' in self.conf( 1564 { 1565 "*:7080": {"pass": "routes"}, 1566 "[::1]:7081": {"pass": "routes"}, 1567 }, 1568 'listeners', 1569 ), 'source listeners configure' 1570 1571 def get_ipv6(): 1572 return self.get(sock_type='ipv6', port=7081) 1573 1574 self.route_match({"source": "127.0.0.1"}) 1575 assert self.get()['status'] == 200, 'exact' 1576 assert get_ipv6()['status'] == 404, 'exact ipv6' 1577 1578 self.route_match({"source": ["127.0.0.1"]}) 1579 assert self.get()['status'] == 200, 'exact 2' 1580 assert get_ipv6()['status'] == 404, 'exact 2 ipv6' 1581 1582 self.route_match({"source": "!127.0.0.1"}) 1583 assert self.get()['status'] == 404, 'exact neg' 1584 assert get_ipv6()['status'] == 200, 'exact neg ipv6' 1585 1586 self.route_match({"source": "127.0.0.2"}) 1587 assert self.get()['status'] == 404, 'exact 3' 1588 assert get_ipv6()['status'] == 404, 'exact 3 ipv6' 1589 1590 self.route_match({"source": "127.0.0.1-127.0.0.1"}) 1591 assert self.get()['status'] == 200, 'range single' 1592 assert get_ipv6()['status'] == 404, 'range single ipv6' 1593 1594 self.route_match({"source": "127.0.0.2-127.0.0.2"}) 1595 assert self.get()['status'] == 404, 'range single 2' 1596 assert get_ipv6()['status'] == 404, 'range single 2 ipv6' 1597 1598 self.route_match({"source": "127.0.0.2-127.0.0.3"}) 1599 assert self.get()['status'] == 404, 'range' 1600 assert get_ipv6()['status'] == 404, 'range ipv6' 1601 1602 self.route_match({"source": "127.0.0.1-127.0.0.2"}) 1603 assert self.get()['status'] == 200, 'range 2' 1604 assert get_ipv6()['status'] == 404, 'range 2 ipv6' 1605 1606 self.route_match({"source": "127.0.0.0-127.0.0.2"}) 1607 assert self.get()['status'] == 200, 'range 3' 1608 assert get_ipv6()['status'] == 404, 'range 3 ipv6' 1609 1610 self.route_match({"source": "127.0.0.0-127.0.0.1"}) 1611 assert self.get()['status'] == 200, 'range 4' 1612 assert get_ipv6()['status'] == 404, 'range 4 ipv6' 1613 1614 self.route_match({"source": "126.0.0.0-127.0.0.0"}) 1615 assert self.get()['status'] == 404, 'range 5' 1616 assert get_ipv6()['status'] == 404, 'range 5 ipv6' 1617 1618 self.route_match({"source": "126.126.126.126-127.0.0.2"}) 1619 assert self.get()['status'] == 200, 'range 6' 1620 assert get_ipv6()['status'] == 404, 'range 6 ipv6' 1621 1622 def test_routes_source_ipv6(self): 1623 assert 'success' in self.conf( 1624 { 1625 "[::1]:7080": {"pass": "routes"}, 1626 "127.0.0.1:7081": {"pass": "routes"}, 1627 }, 1628 'listeners', 1629 ), 'source listeners configure' 1630 1631 self.route_match({"source": "::1"}) 1632 assert self.get(sock_type='ipv6')['status'] == 200, 'exact' 1633 assert self.get(port=7081)['status'] == 404, 'exact ipv4' 1634 1635 self.route_match({"source": ["::1"]}) 1636 assert self.get(sock_type='ipv6')['status'] == 200, 'exact 2' 1637 assert self.get(port=7081)['status'] == 404, 'exact 2 ipv4' 1638 1639 self.route_match({"source": "!::1"}) 1640 assert self.get(sock_type='ipv6')['status'] == 404, 'exact neg' 1641 assert self.get(port=7081)['status'] == 200, 'exact neg ipv4' 1642 1643 self.route_match({"source": "::2"}) 1644 assert self.get(sock_type='ipv6')['status'] == 404, 'exact 3' 1645 assert self.get(port=7081)['status'] == 404, 'exact 3 ipv4' 1646 1647 self.route_match({"source": "::1-::1"}) 1648 assert self.get(sock_type='ipv6')['status'] == 200, 'range' 1649 assert self.get(port=7081)['status'] == 404, 'range ipv4' 1650 1651 self.route_match({"source": "::2-::2"}) 1652 assert self.get(sock_type='ipv6')['status'] == 404, 'range 2' 1653 assert self.get(port=7081)['status'] == 404, 'range 2 ipv4' 1654 1655 self.route_match({"source": "::2-::3"}) 1656 assert self.get(sock_type='ipv6')['status'] == 404, 'range 3' 1657 assert self.get(port=7081)['status'] == 404, 'range 3 ipv4' 1658 1659 self.route_match({"source": "::1-::2"}) 1660 assert self.get(sock_type='ipv6')['status'] == 200, 'range 4' 1661 assert self.get(port=7081)['status'] == 404, 'range 4 ipv4' 1662 1663 self.route_match({"source": "::0-::2"}) 1664 assert self.get(sock_type='ipv6')['status'] == 200, 'range 5' 1665 assert self.get(port=7081)['status'] == 404, 'range 5 ipv4' 1666 1667 self.route_match({"source": "::0-::1"}) 1668 assert self.get(sock_type='ipv6')['status'] == 200, 'range 6' 1669 assert self.get(port=7081)['status'] == 404, 'range 6 ipv4' 1670 1671 def test_routes_source_cidr(self): 1672 assert 'success' in self.conf( 1673 { 1674 "*:7080": {"pass": "routes"}, 1675 "[::1]:7081": {"pass": "routes"}, 1676 }, 1677 'listeners', 1678 ), 'source listeners configure' 1679 1680 def get_ipv6(): 1681 return self.get(sock_type='ipv6', port=7081) 1682 1683 self.route_match({"source": "127.0.0.1/32"}) 1684 assert self.get()['status'] == 200, '32' 1685 assert get_ipv6()['status'] == 404, '32 ipv6' 1686 1687 self.route_match({"source": "127.0.0.0/32"}) 1688 assert self.get()['status'] == 404, '32 2' 1689 assert get_ipv6()['status'] == 404, '32 2 ipv6' 1690 1691 self.route_match({"source": "127.0.0.0/31"}) 1692 assert self.get()['status'] == 200, '31' 1693 assert get_ipv6()['status'] == 404, '31 ipv6' 1694 1695 self.route_match({"source": "0.0.0.0/1"}) 1696 assert self.get()['status'] == 200, '1' 1697 assert get_ipv6()['status'] == 404, '1 ipv6' 1698 1699 self.route_match({"source": "0.0.0.0/0"}) 1700 assert self.get()['status'] == 200, '0' 1701 assert get_ipv6()['status'] == 404, '0 ipv6' 1702 1703 def test_routes_source_cidr_ipv6(self): 1704 assert 'success' in self.conf( 1705 { 1706 "[::1]:7080": {"pass": "routes"}, 1707 "127.0.0.1:7081": {"pass": "routes"}, 1708 }, 1709 'listeners', 1710 ), 'source listeners configure' 1711 1712 self.route_match({"source": "::1/128"}) 1713 assert self.get(sock_type='ipv6')['status'] == 200, '128' 1714 assert self.get(port=7081)['status'] == 404, '128 ipv4' 1715 1716 self.route_match({"source": "::0/128"}) 1717 assert self.get(sock_type='ipv6')['status'] == 404, '128 2' 1718 assert self.get(port=7081)['status'] == 404, '128 ipv4' 1719 1720 self.route_match({"source": "::0/127"}) 1721 assert self.get(sock_type='ipv6')['status'] == 200, '127' 1722 assert self.get(port=7081)['status'] == 404, '127 ipv4' 1723 1724 self.route_match({"source": "::0/32"}) 1725 assert self.get(sock_type='ipv6')['status'] == 200, '32' 1726 assert self.get(port=7081)['status'] == 404, '32 ipv4' 1727 1728 self.route_match({"source": "::0/1"}) 1729 assert self.get(sock_type='ipv6')['status'] == 200, '1' 1730 assert self.get(port=7081)['status'] == 404, '1 ipv4' 1731 1732 self.route_match({"source": "::/0"}) 1733 assert self.get(sock_type='ipv6')['status'] == 200, '0' 1734 assert self.get(port=7081)['status'] == 404, '0 ipv4' 1735 1736 def test_routes_source_unix(self, temp_dir): 1737 addr = temp_dir + '/sock' 1738 1739 assert 'success' in self.conf( 1740 { 1741 "127.0.0.1:7081": {"pass": "routes"}, 1742 "unix:" + addr: {"pass": "routes"}, 1743 }, 1744 'listeners', 1745 ), 'source listeners configure' 1746 1747 self.route_match({"source": "!0.0.0.0/0"}) 1748 assert ( 1749 self.get(sock_type='unix', addr=addr)['status'] == 200 1750 ), 'unix ipv4 neg' 1751 1752 self.route_match({"source": "!::/0"}) 1753 assert ( 1754 self.get(sock_type='unix', addr=addr)['status'] == 200 1755 ), 'unix ipv6 neg' 1756 1757 self.route_match({"source": "unix"}) 1758 assert self.get(port=7081)['status'] == 404, 'unix ipv4' 1759 assert self.get(sock_type='unix', addr=addr)['status'] == 200, 'unix' 1760 1761 def test_routes_match_source(self): 1762 self.route_match({"source": "::"}) 1763 self.route_match( 1764 { 1765 "source": [ 1766 "127.0.0.1", 1767 "192.168.0.10:8080", 1768 "192.168.0.11:8080-8090", 1769 ] 1770 } 1771 ) 1772 self.route_match( 1773 { 1774 "source": [ 1775 "10.0.0.0/8", 1776 "10.0.0.0/7:1000", 1777 "10.0.0.0/32:8080-8090", 1778 ] 1779 } 1780 ) 1781 self.route_match( 1782 { 1783 "source": [ 1784 "10.0.0.0-10.0.0.1", 1785 "10.0.0.0-11.0.0.0:1000", 1786 "127.0.0.0-127.0.0.255:8080-8090", 1787 ] 1788 } 1789 ) 1790 self.route_match( 1791 {"source": ["2001::", "[2002::]:8000", "[2003::]:8080-8090"]} 1792 ) 1793 self.route_match( 1794 { 1795 "source": [ 1796 "2001::-200f:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 1797 "[fe08::-feff::]:8000", 1798 "[fff0::-fff0::10]:8080-8090", 1799 ] 1800 } 1801 ) 1802 self.route_match( 1803 { 1804 "source": [ 1805 "2001::/16", 1806 "[0ff::/64]:8000", 1807 "[fff0:abcd:ffff:ffff:ffff::/128]:8080-8090", 1808 ] 1809 } 1810 ) 1811 self.route_match({"source": "*:0-65535"}) 1812 assert self.get()['status'] == 200, 'source any' 1813 1814 def test_routes_match_source_invalid(self): 1815 self.route_match_invalid({"source": "127"}) 1816 self.route_match_invalid({"source": "256.0.0.1"}) 1817 self.route_match_invalid({"source": "127.0.0."}) 1818 self.route_match_invalid({"source": " 127.0.0.1"}) 1819 self.route_match_invalid({"source": "127.0.0.1:"}) 1820 self.route_match_invalid({"source": "127.0.0.1/"}) 1821 self.route_match_invalid({"source": "11.0.0.0/33"}) 1822 self.route_match_invalid({"source": "11.0.0.0/65536"}) 1823 self.route_match_invalid({"source": "11.0.0.0-10.0.0.0"}) 1824 self.route_match_invalid({"source": "11.0.0.0:3000-2000"}) 1825 self.route_match_invalid({"source": ["11.0.0.0:3000-2000"]}) 1826 self.route_match_invalid({"source": "[2001::]:3000-2000"}) 1827 self.route_match_invalid({"source": "2001::-2000::"}) 1828 self.route_match_invalid({"source": "2001::/129"}) 1829 self.route_match_invalid({"source": "::FFFFF"}) 1830 self.route_match_invalid({"source": "[::1]:"}) 1831 self.route_match_invalid({"source": "[:::]:7080"}) 1832 self.route_match_invalid({"source": "*:"}) 1833 self.route_match_invalid({"source": "*:1-a"}) 1834 self.route_match_invalid({"source": "*:65536"}) 1835 1836 def test_routes_match_source_none(self): 1837 self.route_match({"source": []}) 1838 assert self.get()['status'] == 404, 'source none' 1839 1840 def test_routes_match_destination(self): 1841 assert 'success' in self.conf( 1842 {"*:7080": {"pass": "routes"}, "*:7081": {"pass": "routes"}}, 1843 'listeners', 1844 ), 'listeners configure' 1845 1846 self.route_match({"destination": "*:7080"}) 1847 assert self.get()['status'] == 200, 'dest' 1848 assert self.get(port=7081)['status'] == 404, 'dest 2' 1849 1850 self.route_match({"destination": ["127.0.0.1:7080"]}) 1851 assert self.get()['status'] == 200, 'dest 3' 1852 assert self.get(port=7081)['status'] == 404, 'dest 4' 1853 1854 self.route_match({"destination": "!*:7080"}) 1855 assert self.get()['status'] == 404, 'dest neg' 1856 assert self.get(port=7081)['status'] == 200, 'dest neg 2' 1857 1858 self.route_match({"destination": ['!*:7080', '!*:7081']}) 1859 assert self.get()['status'] == 404, 'dest neg 3' 1860 assert self.get(port=7081)['status'] == 404, 'dest neg 4' 1861 1862 self.route_match({"destination": ['!*:7081', '!*:7082']}) 1863 assert self.get()['status'] == 200, 'dest neg 5' 1864 1865 self.route_match({"destination": ['*:7080', '!*:7080']}) 1866 assert self.get()['status'] == 404, 'dest neg 6' 1867 1868 self.route_match( 1869 {"destination": ['127.0.0.1:7080', '*:7081', '!*:7080']} 1870 ) 1871 assert self.get()['status'] == 404, 'dest neg 7' 1872 assert self.get(port=7081)['status'] == 200, 'dest neg 8' 1873 1874 self.route_match({"destination": ['!*:7081', '!*:7082', '*:7083']}) 1875 assert self.get()['status'] == 404, 'dest neg 9' 1876 1877 self.route_match( 1878 {"destination": ['*:7081', '!127.0.0.1:7080', '*:7080']} 1879 ) 1880 assert self.get()['status'] == 404, 'dest neg 10' 1881 assert self.get(port=7081)['status'] == 200, 'dest neg 11' 1882 1883 assert 'success' in self.conf_delete( 1884 'routes/0/match/destination/0' 1885 ), 'remove destination rule' 1886 assert self.get()['status'] == 404, 'dest neg 12' 1887 assert self.get(port=7081)['status'] == 404, 'dest neg 13' 1888 1889 assert 'success' in self.conf_delete( 1890 'routes/0/match/destination/0' 1891 ), 'remove destination rule 2' 1892 assert self.get()['status'] == 200, 'dest neg 14' 1893 assert self.get(port=7081)['status'] == 404, 'dest neg 15' 1894 1895 assert 'success' in self.conf_post( 1896 "\"!127.0.0.1\"", 'routes/0/match/destination' 1897 ), 'add destination rule' 1898 assert self.get()['status'] == 404, 'dest neg 16' 1899 assert self.get(port=7081)['status'] == 404, 'dest neg 17' 1900 1901 def test_routes_match_destination_proxy(self): 1902 assert 'success' in self.conf( 1903 { 1904 "listeners": { 1905 "*:7080": {"pass": "routes/first"}, 1906 "*:7081": {"pass": "routes/second"}, 1907 }, 1908 "routes": { 1909 "first": [{"action": {"proxy": "http://127.0.0.1:7081"}}], 1910 "second": [ 1911 { 1912 "match": {"destination": ["127.0.0.1:7081"]}, 1913 "action": {"return": 200}, 1914 } 1915 ], 1916 }, 1917 "applications": {}, 1918 } 1919 ), 'proxy configure' 1920 1921 assert self.get()['status'] == 200, 'proxy' 1922