diff --git a/keystoneauth1/discover.py b/keystoneauth1/discover.py index 00b9752a..f03ffbfd 100644 --- a/keystoneauth1/discover.py +++ b/keystoneauth1/discover.py @@ -1415,6 +1415,18 @@ def get_discovery(session, url, cache=None, authenticated=False): if session.auth and hasattr(session.auth, '_discovery_cache'): caches.append(session.auth._discovery_cache) + # https://example.com and https://example.com/ should be treated the same + # for caching purposes. + parsed_url = urllib.parse.urlparse(url) + if parsed_url.path in ('', '/'): + url = urllib.parse.ParseResult( + parsed_url.scheme, + parsed_url.netloc, + '', + parsed_url.params, + parsed_url.query, + parsed_url.fragment).geturl() + for cache in caches: disc = cache.get(url) diff --git a/keystoneauth1/tests/unit/identity/test_identity_common.py b/keystoneauth1/tests/unit/identity/test_identity_common.py index 46fe0aee..2d4c1e9c 100644 --- a/keystoneauth1/tests/unit/identity/test_identity_common.py +++ b/keystoneauth1/tests/unit/identity/test_identity_common.py @@ -341,6 +341,31 @@ class CommonIdentityTests(object): self.assertIn(self.TEST_COMPUTE_ADMIN, discovery_cache.keys()) + def test_discovery_trailing_slash(self): + # The discovery cache should treat root urls the same whether they have + # a slash or not. If the url is called a second time (meaning the cache + # didn't work, we'll hit the 500 error. + self.requests_mock.get( + 'https://example.com', [ + {'json': self.TEST_DISCOVERY}, + {'status_code': 500} + ]) + + sess = session.Session() + discovery_cache = {} + + expected_url = 'https://example.com/v2.0' + + for test_endpoint in ('https://example.com', 'https://example.com/'): + disc = discover.get_discovery( + sess, test_endpoint, cache=discovery_cache) + url = disc.url_for(('2', '0')) + + self.assertEqual(expected_url, url) + + self.assertIn('https://example.com', discovery_cache.keys()) + self.assertNotIn('https://example.com/', discovery_cache.keys()) + def test_discovering_with_no_data(self): # which returns discovery information pointing to TEST_URL but there is # no data there. diff --git a/releasenotes/notes/cache-trailing-slash-3663c86cd9754379.yaml b/releasenotes/notes/cache-trailing-slash-3663c86cd9754379.yaml new file mode 100644 index 00000000..a93167ee --- /dev/null +++ b/releasenotes/notes/cache-trailing-slash-3663c86cd9754379.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Fixed an issue where https://example.com and https://example.com/ were + being treated as different urls in the discovery cache resulting in a + second unneeded discovery call when someone sets an ``endpoint_override`` + that didn't match the trailing-slash form given by that service's + discovery document.