From 9c22ddf01ceb3d6bfb16444db67cf81610c5e7df Mon Sep 17 00:00:00 2001 From: p1c2u Date: Tue, 17 Mar 2020 18:37:44 +0000 Subject: [PATCH] Paths finder paths order fix --- openapi_core/schema/servers/models.py | 11 ++--- openapi_core/templating/paths/finders.py | 12 +++++- tests/unit/templating/test_paths_finders.py | 45 +++++++++++++++++++++ 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/openapi_core/schema/servers/models.py b/openapi_core/schema/servers/models.py index 7c4ac9f..201db26 100644 --- a/openapi_core/schema/servers/models.py +++ b/openapi_core/schema/servers/models.py @@ -1,6 +1,5 @@ """OpenAPI core servers models module""" from six import iteritems -from six.moves.urllib.parse import urljoin class Server(object): @@ -28,15 +27,11 @@ class Server(object): variables = self.default_variables return self.url.format(**variables) - @staticmethod - def is_absolute(url): + def is_absolute(self, url=None): + if url is None: + url = self.url return url.startswith('//') or '://' in url - def get_absolute_url(self, base_url=None): - if base_url is not None and not self.is_absolute(self.url): - return urljoin(base_url, self.url) - return self.url - class ServerVariable(object): diff --git a/openapi_core/templating/paths/finders.py b/openapi_core/templating/paths/finders.py index 30d0a4f..bc90d45 100644 --- a/openapi_core/templating/paths/finders.py +++ b/openapi_core/templating/paths/finders.py @@ -1,6 +1,7 @@ """OpenAPI core templating paths finders module""" from more_itertools import peekable from six import iteritems +from six.moves.urllib.parse import urljoin, urlparse from openapi_core.templating.datatypes import TemplateResult from openapi_core.templating.util import parse, search @@ -63,11 +64,18 @@ class PathFinder(object): for server in servers: server_url_pattern = full_url_pattern.rsplit( path_result.resolved, 1)[0] - server_url = server.get_absolute_url(self.base_url) + server_url = server.url + if not server.is_absolute(): + # relative to absolute url + if self.base_url is not None: + server_url = urljoin(self.base_url, server.url) + # if no base url check only path part + else: + server_url_pattern = urlparse(server_url_pattern).path if server_url.endswith('/'): server_url = server_url[:-1] # simple path - if server_url_pattern.startswith(server_url): + if server_url_pattern == server_url: server_result = TemplateResult(server.url, {}) yield ( path, operation, server, diff --git a/tests/unit/templating/test_paths_finders.py b/tests/unit/templating/test_paths_finders.py index f44a4d3..953cc1e 100644 --- a/tests/unit/templating/test_paths_finders.py +++ b/tests/unit/templating/test_paths_finders.py @@ -390,3 +390,48 @@ class TestPathVariableServerValid( BaseTestVariableValid, BaseTestPathServer, BaseTestSimplePath, BaseTestVariableServer): pass + + +class TestSimilarPaths( + BaseTestSpecServer, BaseTestSimpleServer): + + path_name = '/tokens' + + @pytest.fixture + def operation_2(self): + return Operation('get', '/keys/{id}/tokens', {}, {}) + + @pytest.fixture + def operations_2(self, operation_2): + return { + 'get': operation_2, + } + + @pytest.fixture + def path(self, operations): + return Path('/tokens', operations) + + @pytest.fixture + def path_2(self, operations_2): + return Path('/keys/{id}/tokens', operations_2) + + @pytest.fixture + def paths(self, path, path_2): + return { + path.name: path, + path_2.name: path_2, + } + + def test_valid(self, finder, path_2, operation_2, server): + token_id = '123' + request_uri = '/keys/{0}/tokens'.format(token_id) + request = MockRequest( + 'http://petstore.swagger.io', 'get', request_uri) + + result = finder.find(request) + + path_result = TemplateResult(path_2.name, {'id': token_id}) + server_result = TemplateResult(self.server_url, {}) + assert result == ( + path_2, operation_2, server, path_result, server_result, + )