From 0f4e10c0df08b26e2decfdb649630693f6c34acb Mon Sep 17 00:00:00 2001 From: Kayvan Zahiri <123409429+Kayvan-Zahiri@users.noreply.github.com> Date: Sun, 18 Oct 2026 21:11:25 -0700 Subject: [PATCH] fix: omit JSON bodies on GET requests --- resend/async_request.py | 7 ++- resend/request.py | 7 ++- tests/get_request_body_test.py | 91 ++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 tests/get_request_body_test.py diff --git a/resend/async_request.py b/resend/async_request.py index be17658..2b94247 100644 --- a/resend/async_request.py +++ b/resend/async_request.py @@ -91,8 +91,11 @@ def __get_headers(self) -> HeadersType: async def make_request(self, url: str) -> Union[Dict[str, Any], List[Any]]: headers = self.__get_headers() - if isinstance(self.params, dict): - json_params: Optional[Union[Dict[str, Any], List[Any]]] = { + json_params: Optional[Union[Dict[str, Any], List[Any]]] + if self.verb == "get": + json_params = None + elif isinstance(self.params, dict): + json_params = { str(k): v for k, v in self.params.items() } elif isinstance(self.params, list): diff --git a/resend/request.py b/resend/request.py index 56d27c1..c4326c8 100644 --- a/resend/request.py +++ b/resend/request.py @@ -90,8 +90,11 @@ def __get_headers(self) -> HeadersType: def make_request(self, url: str) -> Union[Dict[str, Any], List[Any]]: headers = self.__get_headers() - if isinstance(self.params, dict): - json_params: Optional[Union[Dict[str, Any], List[Any]]] = { + json_params: Optional[Union[Dict[str, Any], List[Any]]] + if self.verb == "get": + json_params = None + elif isinstance(self.params, dict): + json_params = { str(k): v for k, v in self.params.items() } elif isinstance(self.params, list): diff --git a/tests/get_request_body_test.py b/tests/get_request_body_test.py new file mode 100644 index 0000000..47fe6ae --- /dev/null +++ b/tests/get_request_body_test.py @@ -0,0 +1,91 @@ +import json + +import httpx +import pytest +import requests + +import resend +from resend.http_client_httpx import HTTPXClient + +RESPONSE = {"id": "email-1", "object": "list", "data": [], "has_more": False} +SEND_PARAMS = { + "from": "sender@example.test", + "to": ["recipient@example.test"], + "subject": "Test", + "text": "Test content", +} + + +@pytest.mark.parametrize("operation", ["get", "list", "list_page", "send"]) +def test_sync_email_request_body(monkeypatch, operation): + seen = [] + + def send(session, request, **kwargs): + seen.append(request) + response = requests.Response() + response.status_code = 200 + response.headers["Content-Type"] = "application/json" + response._content = json.dumps(RESPONSE).encode() + return response + + monkeypatch.setattr(requests.Session, "send", send) + monkeypatch.setattr(resend, "api_key", "test-key") + monkeypatch.setattr(resend, "default_http_client", resend.RequestsClient()) + + if operation == "get": + result = resend.Emails.get("email-1") + elif operation == "list": + result = resend.Emails.list() + elif operation == "list_page": + result = resend.Emails.list({"limit": 5, "after": "cursor-1"}) + else: + result = resend.Emails.send(SEND_PARAMS) + + assert result["id"] == "email-1" + request = seen[0] + assert request.headers["Authorization"] == "Bearer test-key" + if operation == "send": + assert json.loads(request.body) == SEND_PARAMS + else: + assert request.body is None + assert "Content-Type" not in request.headers + if operation == "list_page": + assert request.url.endswith("/emails?limit=5&after=cursor-1") + + +@pytest.mark.parametrize("operation", ["get", "list", "list_page", "send"]) +async def test_async_email_request_body(monkeypatch, operation): + seen = [] + + def respond(request): + seen.append(request) + return httpx.Response(200, json=RESPONSE) + + original_client = httpx.AsyncClient + + def client_factory(**kwargs): + return original_client(transport=httpx.MockTransport(respond), **kwargs) + + monkeypatch.setattr(httpx, "AsyncClient", client_factory) + monkeypatch.setattr(resend, "api_key", "test-key") + monkeypatch.setattr(resend, "default_async_http_client", HTTPXClient()) + + if operation == "get": + result = await resend.Emails.get_async("email-1") + elif operation == "list": + result = await resend.Emails.list_async() + elif operation == "list_page": + result = await resend.Emails.list_async({"limit": 5, "after": "cursor-1"}) + else: + result = await resend.Emails.send_async(SEND_PARAMS) + + assert result["id"] == "email-1" + request = seen[0] + assert request.headers["Authorization"] == "Bearer test-key" + if operation == "send": + assert json.loads(request.content) == SEND_PARAMS + else: + assert request.content == b"" + assert "Content-Type" not in request.headers + if operation == "list_page": + assert str(request.url).endswith("/emails?limit=5&after=cursor-1")