diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index d184fd95..728fca4d 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -11,6 +11,10 @@ hide: - Allow passing extensions as string. +### Changed + +- Change `media_type` parameter of `Response` from `MediaType.JSON` to `None` to match the default of the underlying lilya Response. + ### Fixed - OpenAPI responses. diff --git a/docs/en/docs/responses.md b/docs/en/docs/responses.md index be19b49d..fc3cf91e 100644 --- a/docs/en/docs/responses.md +++ b/docs/en/docs/responses.md @@ -39,7 +39,9 @@ This will allow you to use the [ORJSON](#orjson) and [UJSON](#ujson) as well as ### Response -Classic and generic `Response` that fits almost every single use case out there. +Classic and generic `Response` that fits almost every single use case out there. It behaves like lilya `Response` by default. +It has a special mode for `media_type="application/json"` (used by handlers) in which it behaves like `make_response` (encodes content). +This special mode is required for encoding data like datetimes, ... ```python {!> ../../../docs_src/responses/response.py !} diff --git a/esmerald/responses/base.py b/esmerald/responses/base.py index e5cbab55..042d2c28 100644 --- a/esmerald/responses/base.py +++ b/esmerald/responses/base.py @@ -96,7 +96,7 @@ def __init__( The media type used in the response. """ ), - ] = MediaType.JSON, + ] = None, background: Annotated[ Optional[Union["BackgroundTask", "BackgroundTasks"]], Doc( @@ -175,18 +175,27 @@ def __init__( self.cookies = cookies or [] @staticmethod - def transform(value: Any) -> Dict[str, Any]: + def transform( + value: Any, *, encoders: Union[Sequence[Encoder], None] = None + ) -> Dict[str, Any]: """ The transformation of the data being returned. Supports all the default encoders from Lilya and custom from Esmerald. """ return cast( - Dict[str, Any], json_encoder(value, json_encode_fn=dumps, post_transform_fn=loads) + Dict[str, Any], + json_encoder( + value, + json_encode_fn=partial(dumps, option=OPT_SERIALIZE_NUMPY | OPT_OMIT_MICROSECONDS), + post_transform_fn=loads, + with_encoders=encoders, + ), ) def make_response(self, content: Any) -> Union[bytes, str]: # here we need lilyas encoders not only esmerald encoders + # in case no extra encoders are defined use the default by passing None encoders = ( ( ( @@ -208,6 +217,7 @@ def make_response(self, content: Any) -> Union[bytes, str]: ) ): return b"" + # switch to a special mode for MediaType.JSON if self.media_type == MediaType.JSON: return cast( bytes, diff --git a/tests/routing/test_proxy_load.py b/tests/routing/test_proxy_load.py index 2dc3c48c..a505fc4d 100644 --- a/tests/routing/test_proxy_load.py +++ b/tests/routing/test_proxy_load.py @@ -28,9 +28,9 @@ def test_can_load_from_proxy(test_client_factory): response = client.get("/child/home") assert response.status_code == 200 - assert response.json() == "Hello, from proxy" + assert response.text == '"Hello, from proxy"' response = client.get("/esmerald") assert response.status_code == 200 - assert response.json() == "Hello, esmerald" + assert response.text == "Hello, esmerald" diff --git a/tests/routing/test_routing.py b/tests/routing/test_routing.py index d4074f5e..f639afc2 100644 --- a/tests/routing/test_routing.py +++ b/tests/routing/test_routing.py @@ -565,7 +565,7 @@ def test_protocol_switch(test_client_factory): with create_client(routes=mixed_protocol_app) as client: response = client.get("/") assert response.status_code == 200 - assert response.json() == "URL: http://testserver/" + assert response.text == "URL: http://testserver/" with client.websocket_connect("/") as session: assert session.receive_json() == {"URL": "ws://testserver/"} diff --git a/tests/test_responses.py b/tests/test_responses.py index 0ef88b3b..6b7bc083 100644 --- a/tests/test_responses.py +++ b/tests/test_responses.py @@ -52,7 +52,7 @@ def test_override(test_client_factory): with create_client(routes=[Gateway(handler=route_three)]) as client: response = client.get("/three") - assert response.text == '"Ok"' + assert response.text == "Ok" assert response.status_code == status.HTTP_103_EARLY_HINTS @@ -60,7 +60,7 @@ def test_default(test_client_factory): with create_client(routes=[Gateway(handler=route_four)]) as client: response = client.get("/four") - assert response.text == '"Ok"' + assert response.text == "Ok" assert response.status_code == status.HTTP_200_OK @@ -68,7 +68,7 @@ def test_default_decorator(test_client_factory): with create_client(routes=[Gateway(handler=route_five)]) as client: response = client.get("/five") - assert response.text == '"Ok"' + assert response.text == "Ok" assert response.status_code == status.HTTP_207_MULTI_STATUS @@ -92,20 +92,20 @@ def test_multiple(test_client_factory): ) as client: response = client.get("/multi") - assert response.text == '"Ok"' + assert response.text == "Ok" assert response.status_code == status.HTTP_207_MULTI_STATUS response = client.get("/multi/test") - assert response.text == '"Ok"' + assert response.text == "Ok" assert response.status_code == status.HTTP_401_UNAUTHORIZED response = client.get("/multi/esmerald") - assert response.text == '"Ok"' + assert response.text == "Ok" assert response.status_code == status.HTTP_300_MULTIPLE_CHOICES response = client.get("/multi/other") - assert response.text == '"Ok"' + assert response.text == "Ok" assert response.status_code == status.HTTP_207_MULTI_STATUS