From c24c6b1f7de0827cab73589634b51b5bbaa36385 Mon Sep 17 00:00:00 2001 From: Paul Chang Date: Sat, 26 Apr 2025 14:54:21 -0700 Subject: [PATCH 1/2] Fix request_rest to support absolute URLs (closes #79) --- python_anvil/api_resources/requests.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/python_anvil/api_resources/requests.py b/python_anvil/api_resources/requests.py index 296f980d..04e7f42a 100644 --- a/python_anvil/api_resources/requests.py +++ b/python_anvil/api_resources/requests.py @@ -20,7 +20,11 @@ def _request(self, method, url, **kwargs): if method.upper() not in ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]: raise ValueError("Invalid HTTP method provided") - full_url = "/".join([self.get_url(), url]) if len(url) > 0 else self.get_url() + absolute_url = kwargs.pop("absolute_url", False) + if absolute_url: + full_url = url + else: + full_url = "/".join([self.get_url(), url]) if len(url) > 0 else self.get_url() return self._client.request(method, full_url, **kwargs) @@ -64,16 +68,18 @@ def get_url(self): def get(self, url, params=None, **kwargs): retry = kwargs.pop("retry", True) + absolute_url = kwargs.pop("absolute_url", False) content, status_code, headers = self._request( - "GET", url, params=params, retry=retry + "GET", url, params=params, retry=retry, absolute_url=absolute_url ) return self.process_response(content, status_code, headers, **kwargs) def post(self, url, data=None, **kwargs): retry = kwargs.pop("retry", True) + absolute_url = kwargs.pop("absolute_url", False) params = kwargs.pop("params", None) content, status_code, headers = self._request( - "POST", url, json=data, retry=retry, params=params + "POST", url, json=data, retry=retry, params=params, absolute_url=absolute_url ) return self.process_response(content, status_code, headers, **kwargs) From 63bbd28326bca4f9a5f341d93cbd546b439fa3fc Mon Sep 17 00:00:00 2001 From: Paul Chang Date: Sat, 26 Apr 2025 15:45:25 -0700 Subject: [PATCH 2/2] tests --- python_anvil/tests/test_api.py | 52 ++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/python_anvil/tests/test_api.py b/python_anvil/tests/test_api.py index 7d1cdadc..c7851f1b 100644 --- a/python_anvil/tests/test_api.py +++ b/python_anvil/tests/test_api.py @@ -396,3 +396,55 @@ def test_minimum_valid_data_submission(m_request_post, anvil): anvil.forge_submit(payload=payload) assert m_request_post.call_count == 1 assert _expected_data in m_request_post.call_args + + def describe_rest_request_absolute_url_behavior(): + @pytest.mark.parametrize( + "url, expected_absolute_url", + [ + ("some/relative/path", False), + ("https://external.example.com/full/path/file.pdf", True), + ], + ) + @mock.patch("python_anvil.api_resources.requests.AnvilRequest._request") + def test_get_behavior(mock_request, anvil, url, expected_absolute_url): + mock_request.return_value = (b"fake_content", 200, {}) + rest_client = anvil.request_rest() + + if expected_absolute_url: + rest_client.get(url, absolute_url=True) + else: + rest_client.get(url) + + mock_request.assert_called_once_with( + "GET", + url, + params=None, + retry=True, + absolute_url=expected_absolute_url, + ) + + @pytest.mark.parametrize( + "url, expected_absolute_url", + [ + ("some/relative/path", False), + ("https://external.example.com/full/path/file.pdf", True), + ], + ) + @mock.patch("python_anvil.api_resources.requests.AnvilRequest._request") + def test_post_behavior(mock_request, anvil, url, expected_absolute_url): + mock_request.return_value = (b"fake_content", 200, {}) + rest_client = anvil.request_rest() + + if expected_absolute_url: + rest_client.post(url, data={}, absolute_url=True) + else: + rest_client.post(url, data={}) + + mock_request.assert_called_once_with( + "POST", + url, + json={}, + retry=True, + params=None, + absolute_url=expected_absolute_url, + )