Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions qfieldcloud_sdk/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -2131,7 +2131,8 @@ def _request(
"GET requests must not have `data` values passed, use `params` instead"
)

allow_redirects = method != "POST"
if allow_redirects is None:
allow_redirects = method != "POST"

if not skip_token and self.token:
headers_copy["Authorization"] = f"token {self.token}"
Expand Down Expand Up @@ -2175,23 +2176,30 @@ def _request(

if os.environ.get("ENVIRONMENT") == "test":
return request.mock_response()
else:
prepared_request = self.session.prepare_request(request)

# Merge environment settings into session
settings = self.session.merge_environment_settings(
url=prepared_request.url,
proxies={},
stream=stream,
verify=self.verify_ssl,
cert=None,
)
settings = settings | session_params # type: ignore

response = self.session.send(
prepared_request,
timeout=(self.connect_timeout, self.read_timeout),
**settings,
prepared_request = self.session.prepare_request(request)

# Merge environment settings into session
settings = self.session.merge_environment_settings(
url=prepared_request.url,
proxies={},
stream=stream,
verify=self.verify_ssl,
cert=None,
)
settings = settings | session_params # type: ignore

response = self.session.send(
prepared_request,
timeout=(self.connect_timeout, self.read_timeout),
**settings,
)

if not allow_redirects and response.is_redirect:
raise QfcRequestException(
response,
f"Unresolved redirect for {method} {response.url!r}: "
f"{response.status_code} -> {response.headers.get('Location')!r}",
)

try:
Expand Down
25 changes: 24 additions & 1 deletion tests/test_cli_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
import unittest
from unittest import mock

import requests
from click.testing import CliRunner
from requests.structures import CaseInsensitiveDict

from qfieldcloud_sdk.cli import QFIELDCLOUD_DEFAULT_URL, cli
from qfieldcloud_sdk.sdk import Client, Pagination, QfcException
from qfieldcloud_sdk.sdk import Client, Pagination, QfcException, QfcRequestException


class TestSDK(unittest.TestCase):
Expand Down Expand Up @@ -92,6 +94,27 @@ def test_timeout_invalid_arg_value_raises(self):
with self.assertRaises(QfcException):
Client(QFIELDCLOUD_DEFAULT_URL, read_timeout="soon") # type: ignore

def test_request_raises_on_unresolved_post_redirect(self):
fake_response = requests.Response()
fake_response.status_code = 301
fake_response.reason = "Moved Permanently"
fake_response.url = f"{self.client.url}files/some-project/some-file.gpkg/"
fake_response.headers = CaseInsensitiveDict(
{"Location": "http://another-address/files/some-project/some-file.gpkg/"}
)
fake_response._content = b""

# We need to unset the `ENVIRONMENT` variable, because otherwise the client
# would use the mock response and we cannot test the redirect behavior.
with mock.patch.dict(os.environ, {}, clear=False):
os.environ.pop("ENVIRONMENT", None)

with mock.patch.object(
self.client.session, "send", return_value=fake_response
):
with self.assertRaises(QfcRequestException):
self.client._request("POST", "files/some-project/some-file.gpkg")


class TestCLI(unittest.TestCase):
@classmethod
Expand Down
Loading