github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/features/API.feature (about) 1 Feature: Manage proxies wit API. 2 As an authenticated admin user, I need to be able to manage proxies list. 3 4 Scenario: API list must not be available w/out valid JWT token 5 Given request JWT token is not set 6 When I request "/apis" API path with "GET" method 7 Then I should receive 401 response code 8 9 Given request header "Authorization" is set to "Basic YWRtaW46YWRtaW4=" 10 When I request "/apis" API path with "GET" method 11 Then I should receive 401 response code 12 13 Given request header "Authorization" is set to "Bearer InvalidJWT" 14 When I request "/apis" API path with "GET" method 15 Then I should receive 401 response code 16 17 Scenario: API list must return empty list when no endpoints set 18 Given request JWT token is valid admin token 19 When I request "/apis" API path with "GET" method 20 Then I should receive 200 response code 21 And response JSON body is an array of length 0 22 23 Scenario: API should be created with defaults 24 Given request JWT token is valid admin token 25 And request JSON payload: 26 """ 27 { 28 "name":"example", 29 "proxy":{ 30 "listen_path":"/example/*", 31 "upstreams":{ 32 "balancing":"roundrobin", 33 "targets":[ 34 { 35 "target":"http://localhost:9089/hello-world" 36 } 37 ] 38 } 39 } 40 } 41 """ 42 When I request "/apis" API path with "POST" method 43 Then I should receive 201 response code 44 And header "Location" should be "/apis/example" 45 46 When I request "/apis" API path with "GET" method 47 Then I should receive 200 response code 48 And response JSON body is an array of length 1 49 And response JSON body has "0.active" path with value 'true' 50 And response JSON body has "0.proxy.methods" path and is an array of length 1 51 52 Scenario: APIs list and create must be available for user with correct admin token 53 Given request JWT token is valid admin token 54 When I request "/apis" API path with "GET" method 55 Then I should receive 200 response code 56 And response JSON body is an array of length 0 57 58 Given request JSON payload: 59 """ 60 { 61 "name":"example", 62 "active":true, 63 "proxy":{ 64 "preserve_host":false, 65 "listen_path":"/example/*", 66 "upstreams":{ 67 "balancing":"roundrobin", 68 "targets":[ 69 { 70 "target":"http://localhost:9089/hello-world" 71 } 72 ] 73 }, 74 "strip_path":false, 75 "append_path":false, 76 "methods":[ 77 "GET" 78 ] 79 }, 80 "health_check":{ 81 "url":"https://example.com/status" 82 } 83 } 84 """ 85 When I request "/apis" API path with "POST" method 86 Then I should receive 201 response code 87 And header "Location" should be "/apis/example" 88 89 When I request "/apis" API path with "GET" method 90 Then I should receive 200 response code 91 And response JSON body is an array of length 1 92 And response JSON body has "0.name" path with value 'example' 93 And response JSON body has "0.active" path with value 'true' 94 95 Given request JSON payload: 96 """ 97 { 98 "name":"posts", 99 "active":true, 100 "proxy":{ 101 "preserve_host":false, 102 "listen_path":"/posts/*", 103 "upstreams":{ 104 "balancing":"roundrobin", 105 "targets":[ 106 { 107 "target":"http://localhost:9089/posts" 108 } 109 ] 110 }, 111 "strip_path":true, 112 "append_path":false, 113 "methods":[ 114 "ALL" 115 ], 116 "hosts":[ 117 "hellofresh.*" 118 ] 119 }, 120 "plugins":[ 121 { 122 "name":"cors", 123 "enabled":true, 124 "config":{ 125 "domains":[ 126 "*" 127 ], 128 "methods":[ 129 "GET", 130 "POST", 131 "PUT", 132 "PATCH", 133 "DELETE" 134 ], 135 "request_headers":[ 136 "Origin", 137 "Authorization", 138 "Content-Type" 139 ], 140 "exposed_headers":[ 141 "X-Debug-Token", 142 "X-Debug-Token-Link" 143 ] 144 } 145 }, 146 { 147 "name":"rate_limit", 148 "enabled":true, 149 "config":{ 150 "limit":"10-S", 151 "policy":"local" 152 } 153 }, 154 { 155 "name":"oauth2", 156 "enabled":true, 157 "config":{ 158 "server_name":"local" 159 } 160 }, 161 { 162 "name":"compression", 163 "enabled":true 164 } 165 ] 166 } 167 """ 168 When I request "/apis" API path with "POST" method 169 Then I should receive 201 response code 170 And header "Location" should be "/apis/posts" 171 172 When I request "/apis" API path with "GET" method 173 Then I should receive 200 response code 174 And response JSON body is an array of length 2 175 176 Scenario: API fails to create routes with invalid fields 177 Given request JWT token is valid admin token 178 And request JSON payload: 179 """ 180 { 181 "active":true, 182 "proxy":{ 183 "listen_path":"/example/*", 184 "upstreams":{ 185 "balancing":"roundrobin", 186 "targets":[ 187 { 188 "target":"http://localhost:9089/hello-world" 189 } 190 ] 191 } 192 } 193 } 194 """ 195 When I request "/apis" API path with "POST" method 196 Then I should receive 400 response code 197 And the response should contain "name is required" 198 199 Given request JWT token is valid admin token 200 And request JSON payload: 201 """ 202 { 203 "name": "example", 204 "active":true, 205 "proxy":{ 206 "upstreams":{ 207 "balancing":"roundrobin", 208 "targets":[ 209 { 210 "target":"http://localhost:9089/hello-world" 211 } 212 ] 213 } 214 } 215 } 216 """ 217 When I request "/apis" API path with "POST" method 218 Then I should receive 400 response code 219 And the response should contain "proxy.listen_path is required" 220 221 Scenario: API fails to create routes with the same name 222 Given request JWT token is valid admin token 223 And request JSON payload: 224 """ 225 { 226 "name":"example", 227 "active":true, 228 "proxy":{ 229 "preserve_host":false, 230 "listen_path":"/example/*", 231 "upstreams":{ 232 "balancing":"roundrobin", 233 "targets":[ 234 { 235 "target":"http://localhost:9089/hello-world" 236 } 237 ] 238 }, 239 "strip_path":false, 240 "append_path":false, 241 "methods":[ 242 "GET" 243 ] 244 }, 245 "health_check":{ 246 "url":"https://example.com/status" 247 } 248 } 249 """ 250 When I request "/apis" API path with "POST" method 251 Then I should receive 201 response code 252 And header "Location" should be "/apis/example" 253 254 Given request JSON payload: 255 """ 256 { 257 "name":"example", 258 "active":true, 259 "proxy":{ 260 "preserve_host":false, 261 "listen_path":"/example/*", 262 "upstreams":{ 263 "balancing":"roundrobin", 264 "targets":[ 265 { 266 "target":"http://localhost:9089/hello-world" 267 } 268 ] 269 }, 270 "strip_path":false, 271 "append_path":false, 272 "methods":[ 273 "GET" 274 ] 275 }, 276 "health_check":{ 277 "url":"https://example.com/status" 278 } 279 } 280 """ 281 When I request "/apis" API path with "POST" method 282 Then I should receive 409 response code 283 And the response should contain "api name is already registered" 284 285 Given request JSON payload: 286 """ 287 { 288 "name":"example1", 289 "active":true, 290 "proxy":{ 291 "preserve_host":false, 292 "listen_path":"/example/*", 293 "upstreams":{ 294 "balancing":"roundrobin", 295 "targets":[ 296 { 297 "target":"http://localhost:9089/hello-world" 298 } 299 ] 300 }, 301 "strip_path":false, 302 "append_path":false, 303 "methods":[ 304 "GET" 305 ] 306 }, 307 "health_check":{ 308 "url":"https://example.com/status" 309 } 310 } 311 """ 312 When I request "/apis" API path with "POST" method 313 Then I should receive 409 response code 314 And the response should contain "api listen path is already registered" 315 316 Scenario: API must return existing routes and response with error for non-existent 317 Given request JWT token is valid admin token 318 When I request "/apis/example" API path with "GET" method 319 Then I should receive 404 response code 320 321 Given request JSON payload: 322 """ 323 { 324 "name":"example", 325 "active":true, 326 "proxy":{ 327 "preserve_host":false, 328 "listen_path":"/example/*", 329 "upstreams":{ 330 "balancing":"roundrobin", 331 "targets":[ 332 { 333 "target":"http://localhost:9089/hello-world" 334 } 335 ] 336 }, 337 "strip_path":false, 338 "append_path":false, 339 "methods":[ 340 "GET" 341 ] 342 }, 343 "health_check":{ 344 "url":"https://example.com/status" 345 } 346 } 347 """ 348 When I request "/apis" API path with "POST" method 349 Then I should receive 201 response code 350 351 When I request "/apis/example" API path with "GET" method 352 Then I should receive 200 response code 353 And response JSON body has "name" path with value 'example' 354 355 When I request "/apis/example" API path with "DELETE" method 356 Then I should receive 204 response code 357 358 Scenario: API must update existing routes with new path value 359 Given request JWT token is valid admin token 360 And request JSON payload: 361 """ 362 { 363 "name":"example", 364 "active":true, 365 "proxy":{ 366 "preserve_host":false, 367 "listen_path":"/example/*", 368 "upstreams":{ 369 "balancing":"roundrobin", 370 "targets":[ 371 { 372 "target":"http://localhost:9089/hello-world" 373 } 374 ] 375 }, 376 "strip_path":false, 377 "append_path":false, 378 "methods":[ 379 "GET" 380 ] 381 }, 382 "health_check":{ 383 "url":"https://example.com/status" 384 } 385 } 386 """ 387 When I request "/apis" API path with "POST" method 388 Then I should receive 201 response code 389 And header "Location" should be "/apis/example" 390 391 When I request "/apis/example" API path with "GET" method 392 Then I should receive 200 response code 393 And response JSON body has "name" path with value 'example' 394 And response JSON body has "proxy.listen_path" path with value '/example/*' 395 396 Given request JSON payload: 397 """ 398 { 399 "name":"example", 400 "active":true, 401 "proxy":{ 402 "preserve_host":false, 403 "listen_path":"/example1/*", 404 "upstreams":{ 405 "balancing":"roundrobin", 406 "targets":[ 407 { 408 "target":"http://localhost:9089/hello-world" 409 } 410 ] 411 }, 412 "strip_path":false, 413 "append_path":false, 414 "methods":[ 415 "GET" 416 ] 417 }, 418 "health_check":{ 419 "url":"https://example.com/status" 420 } 421 } 422 """ 423 When I request "/apis/example" API path with "PUT" method 424 Then I should receive 200 response code 425 426 When I request "/apis/example" API path with "GET" method 427 Then I should receive 200 response code 428 And response JSON body has "name" path with value 'example' 429 And response JSON body has "proxy.listen_path" path with value '/example1/*' 430 431 When I request "/apis/foo-bar" API path with "GET" method 432 Then I should receive 404 response code 433 434 Scenario: API must update existing routes with new forwarding timeouts 435 Given request JWT token is valid admin token 436 And request JSON payload: 437 """ 438 { 439 "name":"example", 440 "active":true, 441 "proxy":{ 442 "preserve_host":false, 443 "listen_path":"/example/*", 444 "upstreams":{ 445 "balancing":"roundrobin", 446 "targets":[ 447 { 448 "target":"http://localhost:9089/hello-world" 449 } 450 ] 451 }, 452 "strip_path":false, 453 "append_path":false, 454 "methods":[ 455 "GET" 456 ], 457 "forwarding_timeouts": { 458 "dial_timeout": "5s", 459 "response_header_timeout": "7s" 460 } 461 }, 462 "health_check":{ 463 "url":"https://example.com/status" 464 } 465 } 466 """ 467 When I request "/apis" API path with "POST" method 468 Then I should receive 201 response code 469 And header "Location" should be "/apis/example" 470 471 When I request "/apis/example" API path with "GET" method 472 Then I should receive 200 response code 473 And response JSON body has "proxy.forwarding_timeouts.dial_timeout" path with value '5s' 474 And response JSON body has "proxy.forwarding_timeouts.response_header_timeout" path with value '7s' 475 476 Given request JSON payload: 477 """ 478 { 479 "name":"example", 480 "active":true, 481 "proxy":{ 482 "preserve_host":false, 483 "listen_path":"/example/*", 484 "upstreams":{ 485 "balancing":"roundrobin", 486 "targets":[ 487 { 488 "target":"http://localhost:9089/hello-world" 489 } 490 ] 491 }, 492 "strip_path":false, 493 "append_path":false, 494 "methods":[ 495 "GET" 496 ], 497 "forwarding_timeouts": { 498 "dial_timeout": "15s", 499 "response_header_timeout": "17s" 500 } 501 }, 502 "health_check":{ 503 "url":"https://example.com/status" 504 } 505 } 506 """ 507 When I request "/apis/example" API path with "PUT" method 508 Then I should receive 200 response code 509 510 When I request "/apis/example" API path with "GET" method 511 Then I should receive 200 response code 512 And response JSON body has "proxy.forwarding_timeouts.dial_timeout" path with value '15s' 513 And response JSON body has "proxy.forwarding_timeouts.response_header_timeout" path with value '17s' 514 515 Scenario: API must delete existing routes 516 Given request JWT token is valid admin token 517 And request JSON payload: 518 """ 519 { 520 "name":"example", 521 "active":true, 522 "proxy":{ 523 "preserve_host":false, 524 "listen_path":"/example/*", 525 "upstreams":{ 526 "balancing":"roundrobin", 527 "targets":[ 528 { 529 "target":"http://localhost:9089/hello-world" 530 } 531 ] 532 }, 533 "strip_path":false, 534 "append_path":false, 535 "methods":[ 536 "GET" 537 ] 538 }, 539 "health_check":{ 540 "url":"https://example.com/status" 541 } 542 } 543 """ 544 When I request "/apis" API path with "POST" method 545 Then I should receive 201 response code 546 And header "Location" should be "/apis/example" 547 548 Given request JSON payload: 549 """ 550 { 551 "name":"posts", 552 "active":true, 553 "proxy":{ 554 "preserve_host":false, 555 "listen_path":"/posts/*", 556 "upstreams":{ 557 "balancing":"roundrobin", 558 "targets":[ 559 { 560 "target":"http://localhost:9089/posts" 561 } 562 ] 563 }, 564 "strip_path":true, 565 "append_path":false, 566 "methods":[ 567 "ALL" 568 ], 569 "hosts":[ 570 "hellofresh.*" 571 ] 572 }, 573 "plugins":[ 574 { 575 "name":"cors", 576 "enabled":true, 577 "config":{ 578 "domains":[ 579 "*" 580 ], 581 "methods":[ 582 "GET", 583 "POST", 584 "PUT", 585 "PATCH", 586 "DELETE" 587 ], 588 "request_headers":[ 589 "Origin", 590 "Authorization", 591 "Content-Type" 592 ], 593 "exposed_headers":[ 594 "X-Debug-Token", 595 "X-Debug-Token-Link" 596 ] 597 } 598 }, 599 { 600 "name":"rate_limit", 601 "enabled":true, 602 "config":{ 603 "limit":"10-S", 604 "policy":"local" 605 } 606 }, 607 { 608 "name":"oauth2", 609 "enabled":true, 610 "config":{ 611 "server_name":"local" 612 } 613 }, 614 { 615 "name":"compression", 616 "enabled":true 617 } 618 ] 619 } 620 """ 621 When I request "/apis" API path with "POST" method 622 Then I should receive 201 response code 623 And header "Location" should be "/apis/posts" 624 625 When I request "/apis" API path with "GET" method 626 Then I should receive 200 response code 627 And response JSON body is an array of length 2 628 629 When I request "/apis/example" API path with "DELETE" method 630 Then I should receive 204 response code 631 632 When I request "/apis" API path with "GET" method 633 Then I should receive 200 response code 634 And response JSON body is an array of length 1 635 636 When I request "/apis/example" API path with "DELETE" method 637 Then I should receive 404 response code 638 639 When I request "/apis/posts" API path with "DELETE" method 640 Then I should receive 204 response code 641 642 When I request "/apis" API path with "GET" method 643 Then I should receive 200 response code 644 And response JSON body is an array of length 0 645 646 When I request "/apis/posts" API path with "DELETE" method 647 Then I should receive 404 response code 648 649 Scenario: API fails to create oauth servers with the same name 650 Given request JWT token is valid admin token 651 And request JSON payload: 652 """ 653 { 654 "name" : "oauth-server-test", 655 "oauth_endpoints" : { 656 "authorize" : { 657 "listen_path" : "/auth/github/authorize", 658 "methods" : [ 659 "ALL" 660 ], 661 "preserve_host" : false, 662 "strip_path" : false, 663 "upstreams":{ 664 "balancing":"roundrobin", 665 "targets":[ 666 { 667 "target":"https://github.com/login/oauth/authorize" 668 } 669 ] 670 } 671 }, 672 "token" : { 673 "listen_path" : "/auth/github/token", 674 "methods" : [ 675 "GET", 676 "POST" 677 ], 678 "preserve_host" : false, 679 "strip_path" : false, 680 "upstreams":{ 681 "balancing":"roundrobin", 682 "targets":[ 683 { 684 "target":"https://github.com/login/oauth/access_token" 685 } 686 ] 687 } 688 }, 689 "introspect" : { 690 "listen_path" : "/auth/github/introspect", 691 "methods" : [ 692 "GET" 693 ], 694 "preserve_host" : false, 695 "strip_path" : false, 696 "upstreams":{ 697 "balancing":"roundrobin", 698 "targets":[ 699 { 700 "target":"https://api.github.com/user" 701 } 702 ] 703 } 704 } 705 }, 706 "secrets" : { 707 "admin" : "admin" 708 }, 709 "cors_meta" : { 710 "domains" : [ 711 "*" 712 ], 713 "methods" : [ 714 "GET", 715 "POST", 716 "PUT", 717 "PATCH", 718 "DELETE" 719 ], 720 "request_headers" : [ 721 "Origin", 722 "Authorization", 723 "Content-Type" 724 ], 725 "exposed_headers" : [ 726 "X-Debug-Token", 727 "X-Debug-Token-Link" 728 ], 729 "enabled" : true 730 }, 731 "rate_limit" : { 732 "limit" : "200-S" 733 }, 734 "token_strategy" : { 735 "name" : "introspection", 736 "settings" : { 737 "use_auth_header" : true, 738 "auth_header_type" : "token" 739 } 740 } 741 } 742 """ 743 When I request "/oauth/servers" API path with "POST" method 744 Then I should receive 201 response code 745 746 Given request JSON payload: 747 """ 748 { 749 "name" : "oauth-server-test", 750 "oauth_endpoints" : { 751 "authorize" : { 752 "listen_path" : "/auth/github/authorize", 753 "methods" : [ 754 "ALL" 755 ], 756 "preserve_host" : false, 757 "strip_path" : false, 758 "upstreams":{ 759 "balancing":"roundrobin", 760 "targets":[ 761 { 762 "target":"https://github.com/login/oauth/authorize" 763 } 764 ] 765 } 766 }, 767 "token" : { 768 "listen_path" : "/auth/github/token", 769 "methods" : [ 770 "GET", 771 "POST" 772 ], 773 "preserve_host" : false, 774 "strip_path" : false, 775 "upstreams":{ 776 "balancing":"roundrobin", 777 "targets":[ 778 { 779 "target":"https://github.com/login/oauth/access_token" 780 } 781 ] 782 } 783 }, 784 "introspect" : { 785 "listen_path" : "/auth/github/introspect", 786 "methods" : [ 787 "GET" 788 ], 789 "preserve_host" : false, 790 "strip_path" : false, 791 "upstreams":{ 792 "balancing":"roundrobin", 793 "targets":[ 794 { 795 "target":"https://api.github.com/user" 796 } 797 ] 798 } 799 } 800 }, 801 "secrets" : { 802 "admin" : "admin" 803 }, 804 "cors_meta" : { 805 "domains" : [ 806 "*" 807 ], 808 "methods" : [ 809 "GET", 810 "POST", 811 "PUT", 812 "PATCH", 813 "DELETE" 814 ], 815 "request_headers" : [ 816 "Origin", 817 "Authorization", 818 "Content-Type" 819 ], 820 "exposed_headers" : [ 821 "X-Debug-Token", 822 "X-Debug-Token-Link" 823 ], 824 "enabled" : true 825 }, 826 "rate_limit" : { 827 "limit" : "200-S" 828 }, 829 "token_strategy" : { 830 "name" : "introspection", 831 "settings" : { 832 "use_auth_header" : true, 833 "auth_header_type" : "token" 834 } 835 } 836 } 837 """ 838 When I request "/oauth/servers" API path with "POST" method 839 Then I should receive 409 response code 840 And the response should contain "oauth server name is already registered"