|
6 | 6 |
|
7 | 7 | import sentry_sdk |
8 | 8 | from sentry_sdk import capture_message |
9 | | -from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware, _ScopedResponse |
| 9 | +from sentry_sdk.integrations.wsgi import ( |
| 10 | + SentryWsgiMiddleware, |
| 11 | + _ScopedResponse, |
| 12 | + get_request_url, |
| 13 | +) |
10 | 14 |
|
11 | 15 |
|
12 | 16 | @pytest.fixture |
@@ -547,3 +551,94 @@ def app(environ, start_response): |
547 | 551 | assert isinstance(result, _ScopedResponse) |
548 | 552 | else: |
549 | 553 | assert result is response_mock |
| 554 | + |
| 555 | + |
| 556 | +@pytest.mark.parametrize( |
| 557 | + "environ,use_x_forwarded_for,expected_url", |
| 558 | + [ |
| 559 | + # Without use_x_forwarded_for, wsgi.url_scheme is used |
| 560 | + ( |
| 561 | + { |
| 562 | + "wsgi.url_scheme": "http", |
| 563 | + "SERVER_NAME": "example.com", |
| 564 | + "SERVER_PORT": "80", |
| 565 | + "PATH_INFO": "/test", |
| 566 | + "HTTP_X_FORWARDED_PROTO": "https", |
| 567 | + }, |
| 568 | + False, |
| 569 | + "http://example.com/test", |
| 570 | + ), |
| 571 | + # With use_x_forwarded_for, HTTP_X_FORWARDED_PROTO is respected |
| 572 | + ( |
| 573 | + { |
| 574 | + "wsgi.url_scheme": "http", |
| 575 | + "SERVER_NAME": "example.com", |
| 576 | + "SERVER_PORT": "80", |
| 577 | + "PATH_INFO": "/test", |
| 578 | + "HTTP_X_FORWARDED_PROTO": "https", |
| 579 | + }, |
| 580 | + True, |
| 581 | + "https://example.com/test", |
| 582 | + ), |
| 583 | + # With use_x_forwarded_for but no forwarded proto, wsgi.url_scheme is used |
| 584 | + ( |
| 585 | + { |
| 586 | + "wsgi.url_scheme": "http", |
| 587 | + "SERVER_NAME": "example.com", |
| 588 | + "SERVER_PORT": "80", |
| 589 | + "PATH_INFO": "/test", |
| 590 | + }, |
| 591 | + True, |
| 592 | + "http://example.com/test", |
| 593 | + ), |
| 594 | + # Forwarded host with default https port is stripped using forwarded proto |
| 595 | + ( |
| 596 | + { |
| 597 | + "wsgi.url_scheme": "http", |
| 598 | + "SERVER_NAME": "internal", |
| 599 | + "SERVER_PORT": "80", |
| 600 | + "PATH_INFO": "/test", |
| 601 | + "HTTP_X_FORWARDED_PROTO": "https", |
| 602 | + "HTTP_X_FORWARDED_HOST": "example.com:443", |
| 603 | + }, |
| 604 | + True, |
| 605 | + "https://example.com/test", |
| 606 | + ), |
| 607 | + # Forwarded host with non-default port is preserved |
| 608 | + ( |
| 609 | + { |
| 610 | + "wsgi.url_scheme": "http", |
| 611 | + "SERVER_NAME": "internal", |
| 612 | + "SERVER_PORT": "80", |
| 613 | + "PATH_INFO": "/test", |
| 614 | + "HTTP_X_FORWARDED_PROTO": "https", |
| 615 | + "HTTP_X_FORWARDED_HOST": "example.com:8443", |
| 616 | + }, |
| 617 | + True, |
| 618 | + "https://example.com:8443/test", |
| 619 | + ), |
| 620 | + # Forwarded proto with HTTP_HOST (no forwarded host) strips default port |
| 621 | + ( |
| 622 | + { |
| 623 | + "wsgi.url_scheme": "http", |
| 624 | + "HTTP_HOST": "example.com:443", |
| 625 | + "SERVER_NAME": "internal", |
| 626 | + "SERVER_PORT": "80", |
| 627 | + "PATH_INFO": "/test", |
| 628 | + "HTTP_X_FORWARDED_PROTO": "https", |
| 629 | + }, |
| 630 | + True, |
| 631 | + "https://example.com/test", |
| 632 | + ), |
| 633 | + ], |
| 634 | + ids=[ |
| 635 | + "ignores_forwarded_proto_when_disabled", |
| 636 | + "respects_forwarded_proto_when_enabled", |
| 637 | + "falls_back_to_url_scheme_when_no_forwarded_proto", |
| 638 | + "strips_default_https_port_from_forwarded_host", |
| 639 | + "preserves_non_default_port_on_forwarded_host", |
| 640 | + "strips_default_port_from_http_host_with_forwarded_proto", |
| 641 | + ], |
| 642 | +) |
| 643 | +def test_get_request_url_x_forwarded_proto(environ, use_x_forwarded_for, expected_url): |
| 644 | + assert get_request_url(environ, use_x_forwarded_for) == expected_url |
0 commit comments