From 2718bdd2653105c01c3713cb6267d755e5fca1db Mon Sep 17 00:00:00 2001 From: Julien Sagnard Date: Tue, 18 Dec 2018 17:20:46 +0100 Subject: [PATCH] No default header, use prefix header instead of base path header --- connexion/apis/abstract.py | 10 ++++----- connexion/apis/aiohttp_api.py | 4 ++-- connexion/apis/flask_api.py | 6 ++++-- connexion/options.py | 6 +++--- docs/cookbook.rst | 26 +++++++++++------------- tests/aiohttp/test_aiohttp_simple_api.py | 7 ++++--- tests/api/test_responses.py | 2 +- tests/conftest.py | 1 + 8 files changed, 32 insertions(+), 30 deletions(-) diff --git a/connexion/apis/abstract.py b/connexion/apis/abstract.py index 2281e76dc..ca98c0163 100644 --- a/connexion/apis/abstract.py +++ b/connexion/apis/abstract.py @@ -81,7 +81,7 @@ def __init__(self, specification, base_path=None, arguments=None, 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, - 'original_uri_header': self.options.original_uri_header + 'proxy_uri_prefix_header': self.options.proxy_uri_prefix_header }) self._set_base_path(base_path) @@ -137,17 +137,17 @@ def add_swagger_ui(self): Adds swagger ui to {base_path}/ui/ """ - def _get_specs_behind_proxy(self, original_uri): + def _get_specs_behind_proxy(self, prefix_uri): """ 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 + :param prefix_uri: uri to use to prefix base_path :return: Updated raw specifications """ - if not original_uri: + if not prefix_uri: return self.specification.raw specs = copy.copy(self.specification.raw) - self.specification.set_base_path(specs, original_uri) + self.specification.set_base_path(specs, prefix_uri + self.base_path) return specs @abc.abstractmethod diff --git a/connexion/apis/aiohttp_api.py b/connexion/apis/aiohttp_api.py index b495f14fc..3c6888361 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(self.options.original_uri_header)) + specs = self._get_specs_behind_proxy(req.headers.get(self.options.proxy_uri_prefix_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(self.options.original_uri_header, self.base_path) + base_path = req.headers.get(self.options.proxy_uri_prefix_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 28ff24848..8360d34d8 100644 --- a/connexion/apis/flask_api.py +++ b/connexion/apis/flask_api.py @@ -38,7 +38,9 @@ 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(self.options.original_uri_header)) + self._get_specs_behind_proxy( + flask.request.headers.get(self.options.proxy_uri_prefix_header) + ) ) ) @@ -281,7 +283,7 @@ def console_ui_home(self): :return: """ - base_path = flask.request.headers.get(self.options.original_uri_header, self.base_path) + base_path = flask.request.headers.get(self.options.proxy_uri_prefix_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 82e0f31e2..da356900d 100644 --- a/connexion/options.py +++ b/connexion/options.py @@ -121,13 +121,13 @@ def uri_parser_class(self): return self._options.get('uri_parser_class', None) @property - def original_uri_header(self): + def proxy_uri_prefix_header(self): # type: () -> str """ - The header to use to dynamically adapt spec base_path. + The header to use to dynamically prefix spec base_path. Default: None """ - return self._options.get('original_uri_header', 'X-Original-URI') + return self._options.get('proxy_uri_prefix_header', '') def filter_values(dictionary): diff --git a/docs/cookbook.rst b/docs/cookbook.rst index cceb404e4..f8fadcce1 100644 --- a/docs/cookbook.rst +++ b/docs/cookbook.rst @@ -132,9 +132,17 @@ Access application under subpath through NGINX Sometimes, it's interesting to setup your application behind a reverse proxy with a rewrite rule. -By default, Connexion will have a look to X-Original-URI header. -If present, base_path will be dynamically adapted -For example with NGINX: +In this case, you can use `proxy_uri_prefix_header` option to specify a +header name which will contains prefix to prepend to specifications base path. + +.. code-block:: python + + import connexion + app = connexion.FlaskApp(__name__, options={'proxy_uri_prefix_header': 'X-Forwarded-Prefix'}) + app.add_api('swagger.yaml') + app.run(port=8080) + +Corresponding NGINX configuration: .. code-block:: NGINX @@ -142,15 +150,5 @@ For example with NGINX: # Define the location of the proxy server to send the request to proxy_pass http://web:8000; # Add original URI header - proxy_set_header X-Original-URI $request_uri; + proxy_set_header X-Forwarded-Prefix /api; } - -You can customize header name using `original_uri_header` option: - -.. code-block:: python - - import connexion - app = connexion.FlaskApp(__name__, options={'original_uri_header': 'My-URI-Header'}) - app.add_api('swagger.yaml') - app.run(port=8080) - diff --git a/tests/aiohttp/test_aiohttp_simple_api.py b/tests/aiohttp/test_aiohttp_simple_api.py index 2b6392e64..83bb20c2e 100644 --- a/tests/aiohttp/test_aiohttp_simple_api.py +++ b/tests/aiohttp/test_aiohttp_simple_api.py @@ -145,11 +145,12 @@ def test_swagger_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={'proxy_uri_prefix_header': 'X-Forwarded-Prefix'}, debug=True) api = app.add_api('swagger.yaml') app_client = yield from aiohttp_client(app.app) - headers = {'X-Original-URI': '/behind/proxy/v1.0'} + headers = {'X-Forwarded-Prefix': '/behind/proxy'} swagger_ui = yield from app_client.get('/v1.0/ui/', headers=headers) assert swagger_ui.status == 200 @@ -171,12 +172,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'}, + options={'proxy_uri_prefix_header': 'My-URI-Header'}, debug=True) api = app.add_api('openapi.yaml') app_client = yield from aiohttp_client(app.app) - headers = {'My-URI-Header': '/behind/proxy/v1.0'} + headers = {'My-URI-Header': '/behind/proxy'} swagger_ui = yield from app_client.get('/v1.0/ui/', headers=headers) assert swagger_ui.status == 200 diff --git a/tests/api/test_responses.py b/tests/api/test_responses.py index 70886b21a..b9b49ce13 100644 --- a/tests/api/test_responses.py +++ b/tests/api/test_responses.py @@ -46,7 +46,7 @@ def test_app(simple_app): def test_openapi_json_behind_proxy(simple_app): """ Verify the swagger.json file is returned with base_path updated according to X-Original-URI header. """ app_client = simple_app.app.test_client() - headers = {'X-Original-URI': '/behind/proxy/v1.0'} + headers = {'X-Forwarded-Prefix': '/behind/proxy'} swagger_ui = app_client.get('/v1.0/ui/', headers=headers) assert swagger_ui.status_code == 200 diff --git a/tests/conftest.py b/tests/conftest.py index c45cb1573..de750049c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -103,6 +103,7 @@ def build_app_from_fixture(api_spec_folder, spec_file='openapi.yaml', **kwargs): cnx_app = App(__name__, port=5001, specification_dir=FIXTURES_FOLDER / api_spec_folder, + options={'proxy_uri_prefix_header': 'X-Forwarded-Prefix'}, debug=debug) cnx_app.add_api(spec_file, **kwargs)