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