Skip to content

Commit

Permalink
Validate X-Forwarded-Prefix value
Browse files Browse the repository at this point in the history
  • Loading branch information
index-git committed Sep 21, 2023
1 parent 1ba38bf commit 32642f3
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 2 deletions.
2 changes: 1 addition & 1 deletion doc/client-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ By default, Layman will not adjust URLs in its response to contain also URL path

## X-Forwarded-Prefix HTTP header

The value of the `X-Forwarded-Prefix` HTTP header will be used as prefix in some URL paths of Layman response.
The value of the `X-Forwarded-Prefix` HTTP header will be used as prefix in some URL paths of Layman response and is required to match regular expression `^(?:/[a-z0-9_-]+)*$`.

For example, if you send request to `/layman-client-proxy/rest/publications` with HTTP header `X-Forwarded-Prefix=/layman-client-proxy` then response will change to

Expand Down
1 change: 1 addition & 0 deletions src/layman/error_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@
51: (500, 'Error when generating thumbnail'),
52: (400, 'GeoServer HTTP or connection error'),
53: (500, 'Error when publishing on GeoServer. It happens for example for raster files with wrong explicit CRS.'),
54: (400, 'Wrong header value'),
}
13 changes: 12 additions & 1 deletion src/layman/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,4 +548,15 @@ def ensure_home_dir():


def get_x_forwarded_prefix(request_headers):
return request_headers.get('X-Forwarded-Prefix')
header_key = 'X-Forwarded-Prefix'
header_value = request_headers.get(header_key)
if header_value and not re.match(CLIENT_PROXY_PATTERN, header_value):
raise LaymanError(54,
{'header': header_key,
'message': f'Optional header {header_key} is expected to be valid URL subpath starting with slash, or empty string.',
'expected': f'Expected header matching regular expression {CLIENT_PROXY_PATTERN}',
'found': header_value,

}
)
return header_value
21 changes: 21 additions & 0 deletions src/layman/util_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import importlib
import pytest

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


Expand Down Expand Up @@ -143,3 +144,23 @@ def test__url_for(endpoint, internal, params, expected_url):
def test_get_x_forwarded_prefix(headers, exp_result):
result = util.get_x_forwarded_prefix(headers)
assert result == exp_result


@pytest.mark.parametrize('headers, exp_error', [
pytest.param(
{'X-Forwarded-Prefix': 'layman-proxy'},
{
'http_code': 400,
'code': 54,
'data': {
'header': 'X-Forwarded-Prefix',
'message': 'Optional header X-Forwarded-Prefix is expected to be valid URL subpath starting with slash, or empty string.',
'expected': 'Expected header matching regular expression ^(?:/[a-z0-9_-]+)*$',
'found': 'layman-proxy',
},
}, id='without_slash'),
])
def test_get_x_forwarded_prefix_raises(headers, exp_error):
with pytest.raises(LaymanError) as exc_info:
util.get_x_forwarded_prefix(headers)
test_util.assert_error(exp_error, exc_info)

0 comments on commit 32642f3

Please sign in to comment.