From 7294e8e3ca0bb04c9ad9757dbd1c4de66f34169b Mon Sep 17 00:00:00 2001 From: voidZXL Date: Wed, 24 Jul 2024 21:59:56 +0800 Subject: [PATCH] fix native response handler --- tests/conftest.py | 1 + tests/test_api/params.py | 5 +++-- tests/test_api/test_api.py | 3 ++- tests/test_api/test_api_flask.py | 6 +++++- utilmeta/core/response/backends/django.py | 11 +++++++++-- utilmeta/core/response/backends/sanic.py | 3 +++ utilmeta/core/response/backends/starlette.py | 3 +++ utilmeta/core/response/backends/werkzeug.py | 3 +++ utilmeta/core/response/base.py | 5 ++++- 9 files changed, 33 insertions(+), 7 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index c895718..2b28892 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -123,6 +123,7 @@ def __init__( connections_override=None, single_thread: bool = False, ): + service._application = None self.service = service self.is_ready = threading.Event() self.error = None diff --git a/tests/test_api/params.py b/tests/test_api/params.py index 81354e3..2f944bf 100644 --- a/tests/test_api/params.py +++ b/tests/test_api/params.py @@ -18,9 +18,9 @@ def get_requests(backend: str = None, asynchronous: bool = False): ] return [ - ('get', 'backend', {}, None, {}, backend, 200), # (method, path, query, data, headers, result, status) ("get", "@special", {}, None, {}, "@special", 200), + ('get', 'backend', {}, None, {}, backend, 200), ( "post", "response", @@ -292,7 +292,8 @@ def do_live_api_tests(service): ) assert isinstance(resp, Response), f'invalid response: {resp}' content = resp.data - assert resp.status == status, f"{method} {path} failed with {content}, {status} expected, got {resp.status}" + assert resp.status == status, \ + f"{method} {path} failed with {content}, {status} expected, got {resp.status}, {resp.headers}" if result is not ...: if callable(result): result(content) diff --git a/tests/test_api/test_api.py b/tests/test_api/test_api.py index 5bdad20..a7a5fde 100644 --- a/tests/test_api/test_api.py +++ b/tests/test_api/test_api.py @@ -120,7 +120,8 @@ def test_api_features(self): )() assert isinstance(resp, response.Response), f'invalid response: {resp}' content = resp.data - assert resp.status == status, f"{method} {path} failed with {content}, {status} expected, got {resp.status}" + assert resp.status == status, \ + f"{method} {path} failed with {content}, {status} expected, got {resp.status}" if result is not ...: if callable(result): result(content) diff --git a/tests/test_api/test_api_flask.py b/tests/test_api/test_api_flask.py index 6c9239f..25640e2 100644 --- a/tests/test_api/test_api_flask.py +++ b/tests/test_api/test_api_flask.py @@ -2,18 +2,22 @@ from .params import do_live_api_tests from utilmeta import UtilMeta -setup_service(__name__, backend='flask') +setup_service(__name__, backend='flask', async_param=[False, True]) flask_server_process = make_live_process(backend='flask', port=8003, cmdline=True) flask_server_thread = make_server_thread(backend='flask', port=8083) def test_flask_api(service, flask_server_process): + service._application = None + service.adaptor.app = None do_live_api_tests(service) service._application = None service.adaptor.app = None def test_flask_api_internal(service: UtilMeta, flask_server_thread): + service._application = None + service.adaptor.app = None do_live_api_tests(service) service._application = None service.adaptor.app = None diff --git a/utilmeta/core/response/backends/django.py b/utilmeta/core/response/backends/django.py index b2e75be..2564f36 100644 --- a/utilmeta/core/response/backends/django.py +++ b/utilmeta/core/response/backends/django.py @@ -15,6 +15,9 @@ def qualify(cls, obj): @classmethod def reconstruct(cls, resp: Union['ResponseAdaptor', 'Response']): + if isinstance(resp, (HttpResponse, StreamingHttpResponse)): + return resp + from utilmeta.core.response import Response if isinstance(resp, ResponseAdaptor): resp = Response(response=resp) @@ -48,9 +51,13 @@ def headers(self): @property def body(self) -> bytes: + if self._body is not None: + return self._body if isinstance(self.response, StreamingHttpResponse): - return self.response.getvalue() - return self.response.content + self._body = self.response.getvalue() + else: + self._body = self.response.content + return self._body @property def cookies(self): diff --git a/utilmeta/core/response/backends/sanic.py b/utilmeta/core/response/backends/sanic.py index 0c7ee0e..b0d4b4a 100644 --- a/utilmeta/core/response/backends/sanic.py +++ b/utilmeta/core/response/backends/sanic.py @@ -22,6 +22,9 @@ def qualify(cls, obj): @classmethod def reconstruct(cls, resp: Union['ResponseAdaptor', 'Response']): + if isinstance(resp, HTTPResponse): + return resp + from utilmeta.core.response import Response if isinstance(resp, ResponseAdaptor): diff --git a/utilmeta/core/response/backends/starlette.py b/utilmeta/core/response/backends/starlette.py index 84378b9..5f408a3 100644 --- a/utilmeta/core/response/backends/starlette.py +++ b/utilmeta/core/response/backends/starlette.py @@ -17,6 +17,9 @@ def qualify(cls, obj): @classmethod def reconstruct(cls, resp: Union['ResponseAdaptor', 'Response']): + if isinstance(resp, HttpResponse): + return resp + from utilmeta.core.response import Response if isinstance(resp, ResponseAdaptor): diff --git a/utilmeta/core/response/backends/werkzeug.py b/utilmeta/core/response/backends/werkzeug.py index 2e86e7a..f57afe1 100644 --- a/utilmeta/core/response/backends/werkzeug.py +++ b/utilmeta/core/response/backends/werkzeug.py @@ -8,6 +8,9 @@ class WerkzeugResponseAdaptor(ResponseAdaptor): @classmethod def reconstruct(cls, resp: Union['ResponseAdaptor', 'WerkzeugResponse']): + if isinstance(resp, WerkzeugResponse): + return resp + from utilmeta.core.response import Response if isinstance(resp, ResponseAdaptor): diff --git a/utilmeta/core/response/base.py b/utilmeta/core/response/base.py index 084c368..2883911 100644 --- a/utilmeta/core/response/base.py +++ b/utilmeta/core/response/base.py @@ -718,7 +718,10 @@ def prepare_body(self): @property def body(self) -> bytes: if self.adaptor: - return self.adaptor.body + body = self.adaptor.body + # sometime adaptor.body maybe only can read once + if body: + return body body = self.prepare_body() if hasattr(body, 'read'): return body.read() # noqa