Skip to content

Commit

Permalink
Use X-Forwarder -Proto and -Host in _url_for
Browse files Browse the repository at this point in the history
  • Loading branch information
jirik committed Sep 25, 2023
1 parent 3615755 commit 1dd5b4b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
11 changes: 7 additions & 4 deletions src/layman/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,17 +331,20 @@ def _url_for(endpoint, *, server_name, proxy_server_name, internal=False, x_forw
x_forwarded_items = x_forwarded_items or XForwardedClass()
assert not (internal and values.get('_external'))
assert not (internal and x_forwarded_items)
x_forwarded_prefix = x_forwarded_items.prefix or ''
protocol = x_forwarded_items.proto or current_app.config['PREFERRED_URL_SCHEME']
host = x_forwarded_items.host or proxy_server_name
path_prefix = x_forwarded_items.prefix or ''
# It seems SERVER_NAME is not None only in some tests. It also seems TESTING is True only in the same tests.
assert (current_app.config.get('SERVER_NAME', None) is not None) == (current_app.config['TESTING'] is True)
# Flask does not accept SERVER_NAME without dot, and without SERVER_NAME url_for cannot be used
# therefore DUMB_MAP_ADAPTER_DICT is created manually ...
dict_key = f"{proxy_server_name} {x_forwarded_prefix}"
dict_key = f"{protocol} {host} {path_prefix}"
dumb_map_adapter = DUMB_MAP_ADAPTER_DICT.get(dict_key)
if dumb_map_adapter is None:
dumb_map_adapter = current_app.url_map.bind(
proxy_server_name + x_forwarded_prefix,
url_scheme=current_app.config['PREFERRED_URL_SCHEME']
host,
script_name=path_prefix,
url_scheme=protocol,
)
DUMB_MAP_ADAPTER_DICT[dict_key] = dumb_map_adapter
result = dumb_map_adapter.build(endpoint, values=values, force_external=True)
Expand Down
33 changes: 24 additions & 9 deletions src/layman/util_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from test_tools import util as test_util
from . import app, settings, LaymanError, util
from .util import XForwardedClass


@pytest.mark.parametrize('unsafe_input, exp_output', [
Expand Down Expand Up @@ -120,21 +121,35 @@ def test_url_for(endpoint, internal, params, expected_url):
assert util.url_for(endpoint, internal=internal, **params) == expected_url


@pytest.mark.parametrize('endpoint, internal, params, expected_url', [
('rest_workspace_maps.get', False, {'workspace': 'workspace_name'},
f'http://enjoychallenge.tech/rest/{settings.REST_WORKSPACES_PREFIX}/workspace_name/maps'),
('rest_workspace_layers.get', False, {'workspace': 'workspace_name'},
f'http://enjoychallenge.tech/rest/{settings.REST_WORKSPACES_PREFIX}/workspace_name/layers'),
('rest_about.get_version', True, {}, 'http://layman:8000/rest/about/version'),
('rest_about.get_version', False, {}, 'http://enjoychallenge.tech/rest/about/version'),
@pytest.mark.parametrize('endpoint, internal, x_forwarded_items, params, expected_url', [
pytest.param('rest_workspace_maps.get', False, None, {'workspace': 'workspace_name'},
f'http://enjoychallenge.tech/rest/{settings.REST_WORKSPACES_PREFIX}/workspace_name/maps',
id='get-workspace-maps-external'),
pytest.param('rest_about.get_version', True, None, {}, 'http://layman:8000/rest/about/version',
id='get-version-internal'),
pytest.param('rest_about.get_version', False, None, {}, 'http://enjoychallenge.tech/rest/about/version',
id='get-version-external'),
pytest.param('rest_workspace_layers.get', False, XForwardedClass(proto='https'), {'workspace': 'workspace_name'},
f'https://enjoychallenge.tech/rest/{settings.REST_WORKSPACES_PREFIX}/workspace_name/layers',
id='get-workspace-layers-x-forwarded-proto'),
pytest.param('rest_workspace_layers.get', False, XForwardedClass(prefix='/proxy'), {'workspace': 'workspace_name'},
f'http://enjoychallenge.tech/proxy/rest/{settings.REST_WORKSPACES_PREFIX}/workspace_name/layers',
id='get-workspace-layers-x-forwarded-prefix'),
pytest.param('rest_workspace_layers.get', False, XForwardedClass(prefix=''), {'workspace': 'workspace_name'},
f'http://enjoychallenge.tech/rest/{settings.REST_WORKSPACES_PREFIX}/workspace_name/layers',
id='get-workspace-layers-x-forwarded-prefix-empty-string'),
pytest.param('rest_workspace_layers.get', False, XForwardedClass(proto='https', host='foo.com', prefix='/proxy'),
{'workspace': 'workspace_name'},
f'https://foo.com/proxy/rest/{settings.REST_WORKSPACES_PREFIX}/workspace_name/layers',
id='get-workspace-layers-x-forwarded-proto-host-prefix'),
])
def test__url_for(endpoint, internal, params, expected_url):
def test__url_for(endpoint, internal, x_forwarded_items, params, expected_url):
server_name = 'layman:8000'
proxy_server_name = 'enjoychallenge.tech'
with app.app_context():
# pylint: disable=protected-access
assert util._url_for(endpoint, server_name=server_name, proxy_server_name=proxy_server_name, internal=internal,
**params) == expected_url
x_forwarded_items=x_forwarded_items, **params) == expected_url


@pytest.mark.parametrize('headers, exp_result', [
Expand Down

0 comments on commit 1dd5b4b

Please sign in to comment.