From d2dd2bbfb5b5467453706e209d1dbba124d980e6 Mon Sep 17 00:00:00 2001 From: James Norton Date: Tue, 23 Apr 2024 10:41:18 -0400 Subject: [PATCH] HARMONY-1752: Add method to Client to access request as url --- harmony/harmony.py | 26 ++++++++++++++++++++++++-- tests/test_client.py | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/harmony/harmony.py b/harmony/harmony.py index 2e59e2d..36e9eb4 100644 --- a/harmony/harmony.py +++ b/harmony/harmony.py @@ -706,11 +706,12 @@ def _params_dict_to_files(self, params: Mapping[str, Any]) -> List[Tuple[None, s result += [(key, (None, str(value), None)) for value in values] return result - def _get_prepared_request(self, request: BaseRequest) -> requests.models.PreparedRequest: + def _get_prepared_request(self, request: BaseRequest, for_browser=False) -> requests.models.PreparedRequest: """Returns a :requests.models.PreparedRequest: object for the given harmony Request Args: request: The Harmony Request to prepare + for_browser: if True only the url with query params will be returned Returns: A PreparedRequest @@ -722,7 +723,7 @@ def _get_prepared_request(self, request: BaseRequest) -> requests.models.Prepare method = self._http_method(request) with self._files(request) as files: - if files or method == 'POST': + if (files or method == 'POST') and not for_browser: # Ideally this should just be files=files, params=params but Harmony # cannot accept both files and query params now. (HARMONY-290) # Inflate params to a list of tuples that can be passed as multipart @@ -742,11 +743,17 @@ def _get_prepared_request(self, request: BaseRequest) -> requests.models.Prepare files=all_files, headers=headers) else: + if files: + raise Exception(f"Cannot include shapefile as URL query parameter") + r = requests.models.Request('GET', self._submit_url(request), params=params, headers=headers) + prepped_request = session.prepare_request(r) + if for_browser: + prepped_request.headers = None return prepped_request @@ -798,6 +805,21 @@ def request_as_curl(self, request: BaseRequest) -> str: prepped_request.prepare_cookies(cooks) return curlify.to_curl(prepped_request) + def request_as_url(self, request: BaseRequest) -> str: + """Returns a URL string representation of the given request. + **Note** Headers and cookies are not included, just the URL. + Shapefiles are not supported. + + Args: + request: The Request to build the URL string for + + Returns: + A URL string that can be pasted into a browser. + :raises + Exception: if a shapefile is included in the request. + """ + return self._get_prepared_request(request, for_browser=True).url + def submit(self, request: BaseRequest) -> any: """Submits a request to Harmony and returns the Harmony Job ID. diff --git a/tests/test_client.py b/tests/test_client.py index 8bc079a..0184b3a 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1502,6 +1502,28 @@ def test_request_as_curl_post(examples_dir): f'/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset' in curl_command assert '-X POST' in curl_command +def test_request_as_url(): + collection = Collection(id='C1940468263-POCLOUD') + request = Request( + collection=collection, + spatial=BBox(-107, 40, -105, 42) + ) + + url = Client(should_validate_auth=False).request_as_url(request) + assert url == 'https://harmony.earthdata.nasa.gov/C1940468263-POCLOUD/ogc-api-coverages/1.0.0/collections/all/coverage/rangeset?forceAsync=true&subset=lat%2840%3A42%29&subset=lon%28-107%3A-105%29' + +def test_request_with_shapefile_as_url(examples_dir): + collection = Collection(id='C1940468263-POCLOUD') + request = Request( + collection=collection, + shape=os.path.join(examples_dir, 'asf_example.json'), + spatial=BBox(-107, 40, -105, 42) + ) + + with pytest.raises(Exception) as e: + Client(should_validate_auth=False).request_as_url(request) + assert str(e.value) == "Cannot include shapefile as URL query parameter" + @responses.activate def test_collection_capabilities(): collection_id='C1940468263-POCLOUD'