diff --git a/CHANGES.rst b/CHANGES.rst index e2665e2b..b9cad21e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -70,6 +70,8 @@ Deprecations and Removals - Adding ``session`` kwarg to allow to pass a session along when turning an Interface into a service via ``Interface.to_service``. [#590] +- Include port number if it is present in endpoint access URL. [#582] + 1.5.2 (2024-05-22) ================== diff --git a/pyvo/dal/tests/test_tap.py b/pyvo/dal/tests/test_tap.py index 4f93eaee..0c22dc84 100644 --- a/pyvo/dal/tests/test_tap.py +++ b/pyvo/dal/tests/test_tap.py @@ -790,3 +790,15 @@ def test_missing_udf(self, tapservice): def test_get_udf(self, tapservice): func = tapservice.get_tap_capability().get_adql().get_udf("IVO_hasword") # case insensitive! assert func.form == "ivo_hasword(haystack TEXT, needle TEXT) -> INTEGER" + + +def test_get_endpoint_candidates(): + # Directly instantiate the TAPService with a known base URL + svc = TAPService("http://astroweb.projects.phys.ucl.ac.uk:8000/tap") + + # Check if the correct endpoint candidates are generated + expected_urls = [ + "http://astroweb.projects.phys.ucl.ac.uk:8000/tap/capabilities", + "http://astroweb.projects.phys.ucl.ac.uk:8000/capabilities" + ] + assert svc._get_endpoint_candidates("capabilities") == expected_urls diff --git a/pyvo/dal/vosi.py b/pyvo/dal/vosi.py index 0cdbd99b..6b7805f4 100644 --- a/pyvo/dal/vosi.py +++ b/pyvo/dal/vosi.py @@ -18,24 +18,21 @@ class EndpointMixin(): - def _get_endpoint(self, endpoint): - # finds the endpoint relative to the base url or its parent - # and returns its content in raw format - - # do not trust baseurl as it might contain query or fragments + def _get_endpoint_candidates(self, endpoint): urlcomp = urlparse(self.baseurl) - curated_baseurl = '{}://{}{}'.format(urlcomp.scheme, - urlcomp.hostname, - urlcomp.path) + # Include the port number if present + netloc = urlcomp.hostname + if urlcomp.port: + netloc += f':{urlcomp.port}' + curated_baseurl = f'{urlcomp.scheme}://{netloc}{urlcomp.path}' + if not endpoint: raise AttributeError('endpoint required') - ep_urls = [ - '{baseurl}/{endpoint}'.format(baseurl=curated_baseurl, - endpoint=endpoint), - url_sibling(curated_baseurl, endpoint) - ] - for ep_url in ep_urls: + return [f'{curated_baseurl}/{endpoint}', url_sibling(curated_baseurl, endpoint)] + + def _get_endpoint(self, endpoint): + for ep_url in self._get_endpoint_candidates(endpoint): try: response = self._session.get(ep_url, stream=True) response.raise_for_status() @@ -43,9 +40,7 @@ def _get_endpoint(self, endpoint): except requests.RequestException: continue else: - raise DALServiceError( - "No working {endpoint} endpoint provided".format( - endpoint=endpoint)) + raise DALServiceError(f"No working {endpoint} endpoint provided") return response.raw @@ -145,6 +140,7 @@ class VOSITables: Access to table names is like accessing dictionary keys. using iterator syntax or `keys()` """ + def __init__(self, vosi_tables, endpoint_url, *, session=None): self._vosi_tables = vosi_tables self._endpoint_url = endpoint_url