diff --git a/nextcore/http/client/client.py b/nextcore/http/client/client.py index 19808ae03..e98a40ee1 100644 --- a/nextcore/http/client/client.py +++ b/nextcore/http/client/client.py @@ -29,7 +29,7 @@ from aiohttp import ClientSession from ... import __version__ as nextcore_version -from ...common import UNDEFINED, Dispatcher, UndefinedType +from ...common import UNDEFINED, Dispatcher, UndefinedType, json_dumps from ..bucket import Bucket from ..bucket_metadata import BucketMetadata from ..errors import ( @@ -45,10 +45,12 @@ from ..rate_limit_storage import RateLimitStorage from ..route import Route from .base_client import BaseHTTPClient +from .client_response import ClientResponse if TYPE_CHECKING: from typing import Any, Final, Literal + # ClientResponse is still imported here because ours is "incompatible" from aiohttp import ClientResponse, ClientWebSocketResponse logger = getLogger(__name__) @@ -189,7 +191,7 @@ async def setup(self) -> None: """ if self._session is not None: raise RuntimeError("This method can only be called once!") - self._session = ClientSession() + self._session = ClientSession(json_serialize=json_dumps, response_class=ClientResponse) async def close(self) -> None: """Clean up internal state""" diff --git a/nextcore/http/client/client_response.py b/nextcore/http/client/client_response.py new file mode 100644 index 000000000..5df20a479 --- /dev/null +++ b/nextcore/http/client/client_response.py @@ -0,0 +1,40 @@ +# The MIT License (MIT) +# Copyright (c) 2021-present tag-epic +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from typing import Any, Optional + +from aiohttp import ClientResponse as _ClientResponse +from aiohttp.typedefs import JSONDecoder + +from ...common import json_loads + + +class ClientResponse(_ClientResponse): + """A patched version of :class:`aiohttp.ClientResponse` that decodes JSON using orjson, if installed.""" + + async def json( + self, + *, + encoding: Optional[str] = None, + loads: JSONDecoder = json_loads, + content_type: Optional[str] = "application/json" + ) -> Any: + return await super().json(encoding=encoding, loads=loads, content_type=content_type)