From bd18b18d0d2c5f5dbe9565092d3a432288c31757 Mon Sep 17 00:00:00 2001 From: Julien Sagnard Date: Tue, 18 Dec 2018 15:21:07 +0100 Subject: [PATCH] Add option to specify header to use --- connexion/apis/abstract.py | 15 ++++++++------- connexion/apis/aiohttp_api.py | 4 ++-- connexion/apis/flask_api.py | 4 ++-- connexion/options.py | 9 +++++++++ tests/aiohttp/test_aiohttp_simple_api.py | 3 ++- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/connexion/apis/abstract.py b/connexion/apis/abstract.py index 141626d79..2281e76dc 100644 --- a/connexion/apis/abstract.py +++ b/connexion/apis/abstract.py @@ -80,7 +80,9 @@ def __init__(self, specification, base_path=None, arguments=None, logger.debug('Options Loaded', extra={'swagger_ui': self.options.openapi_console_ui_available, 'swagger_path': self.options.openapi_console_ui_from_dir, - 'swagger_url': self.options.openapi_console_ui_path}) + 'swagger_url': self.options.openapi_console_ui_path, + 'original_uri_header': self.options.original_uri_header + }) self._set_base_path(base_path) @@ -114,7 +116,7 @@ def __init__(self, specification, base_path=None, arguments=None, self.specification.security_definitions ) - def _set_base_path(self, base_path=None): + def _set_base_path(self, base_path): if base_path is not None: # update spec to include user-provided base_path self.specification.base_path = base_path @@ -135,14 +137,13 @@ def add_swagger_ui(self): Adds swagger ui to {base_path}/ui/ """ - def _get_specs_behind_proxy(self, original_uri_header): + def _get_specs_behind_proxy(self, original_uri): """ - Update OpenAPI base path using X-Original-URI when API is behind a proxy. - :param headers: X-Original-URI header - :return: + Update OpenAPI base path using specified original_uri. (from X-Original-URI when API is behind a proxy). + :param original_uri: uri to use to replace base_path + :return: Updated raw specifications """ - original_uri = original_uri_header if not original_uri: return self.specification.raw specs = copy.copy(self.specification.raw) diff --git a/connexion/apis/aiohttp_api.py b/connexion/apis/aiohttp_api.py index e0c8a59a4..b495f14fc 100644 --- a/connexion/apis/aiohttp_api.py +++ b/connexion/apis/aiohttp_api.py @@ -79,7 +79,7 @@ def add_openapi_json(self): @asyncio.coroutine def _get_openapi_json(self, req): - specs = self._get_specs_behind_proxy(req.headers.get('X-Original-URI')) + specs = self._get_specs_behind_proxy(req.headers.get(self.options.original_uri_header)) return web.Response( status=200, content_type='application/json', @@ -115,7 +115,7 @@ def add_swagger_ui(self): @aiohttp_jinja2.template('index.j2') @asyncio.coroutine def _get_swagger_ui_home(self, req): - base_path = req.headers.get('X-Original-URI', self.base_path) + base_path = req.headers.get(self.options.original_uri_header, self.base_path) return {'openapi_spec_url': (base_path + self.options.openapi_spec_path)} diff --git a/connexion/apis/flask_api.py b/connexion/apis/flask_api.py index 545d2a4d9..28ff24848 100644 --- a/connexion/apis/flask_api.py +++ b/connexion/apis/flask_api.py @@ -38,7 +38,7 @@ def add_openapi_json(self): self.blueprint.add_url_rule(self.options.openapi_spec_path, endpoint_name, lambda: flask.jsonify( - self._get_specs_behind_proxy(flask.request.headers.get('X-Original-URI')) + self._get_specs_behind_proxy(flask.request.headers.get(self.options.original_uri_header)) ) ) @@ -281,7 +281,7 @@ def console_ui_home(self): :return: """ - base_path = flask.request.headers.get('X-Original-URI', self.base_path) + base_path = flask.request.headers.get(self.options.original_uri_header, self.base_path) return flask.render_template( 'index.j2', openapi_spec_url=(base_path + self.options.openapi_spec_path) diff --git a/connexion/options.py b/connexion/options.py index 899acda5a..82e0f31e2 100644 --- a/connexion/options.py +++ b/connexion/options.py @@ -120,6 +120,15 @@ def uri_parser_class(self): """ return self._options.get('uri_parser_class', None) + @property + def original_uri_header(self): + # type: () -> str + """ + The header to use to dynamically adapt spec base_path. + Default: None + """ + return self._options.get('original_uri_header', 'X-Original-URI') + def filter_values(dictionary): # type: (dict) -> dict diff --git a/tests/aiohttp/test_aiohttp_simple_api.py b/tests/aiohttp/test_aiohttp_simple_api.py index 5fcc914f5..2b6392e64 100644 --- a/tests/aiohttp/test_aiohttp_simple_api.py +++ b/tests/aiohttp/test_aiohttp_simple_api.py @@ -171,11 +171,12 @@ def test_openapi_json_behind_proxy(simple_api_spec_dir, aiohttp_client): """ Verify the swagger.json file is returned with base_path updated according to X-Original-URI header. """ app = AioHttpApp(__name__, port=5001, specification_dir=simple_api_spec_dir, + options={'original_uri_header': 'My-URI-Header'}, debug=True) api = app.add_api('openapi.yaml') app_client = yield from aiohttp_client(app.app) - headers = {'X-Original-URI': '/behind/proxy/v1.0'} + headers = {'My-URI-Header': '/behind/proxy/v1.0'} swagger_ui = yield from app_client.get('/v1.0/ui/', headers=headers) assert swagger_ui.status == 200