diff options
author | Andrei Zeliankou <zelenkov@nginx.com> | 2024-01-26 14:58:43 +0000 |
---|---|---|
committer | andrey-zelenkov <xim.andrew@gmail.com> | 2024-02-21 14:06:43 +0000 |
commit | 697a58506235e89af1c8cc3cafc92b3d85a3467d (patch) | |
tree | 67d8cf28089e947ed59d00c24df934a8a9eea956 | |
parent | f71ead5fa5b8bae378a0eca2bedb689cf08a8eff (diff) | |
download | unit-697a58506235e89af1c8cc3cafc92b3d85a3467d.tar.gz unit-697a58506235e89af1c8cc3cafc92b3d85a3467d.tar.bz2 |
Python: bytearray body support for ASGI module.
@filiphanes requested support for bytearray
and memoryview in the request body here:
<https://github.com/nginx/unit/issues/648>
This patch implements bytearray body support only.
Memoryview body still need to be implemented.
-rw-r--r-- | docs/changes.xml | 6 | ||||
-rw-r--r-- | src/python/nxt_python_asgi_http.c | 31 | ||||
-rw-r--r-- | test/python/body_bytearray/asgi.py | 20 | ||||
-rw-r--r-- | test/test_asgi_application.py | 8 |
4 files changed, 53 insertions, 12 deletions
diff --git a/docs/changes.xml b/docs/changes.xml index 833ec20e..ba41f00d 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -80,6 +80,12 @@ can be used as a unique request identifier. <change type="feature"> <para> +bytearray in response body for ASGI applications. +</para> +</change> + +<change type="feature"> +<para> ServerRequest.flushHeaders() implemented in Node.js module to make it compatible with Next.js. </para> diff --git a/src/python/nxt_python_asgi_http.c b/src/python/nxt_python_asgi_http.c index 05c0da4f..cdd6357e 100644 --- a/src/python/nxt_python_asgi_http.c +++ b/src/python/nxt_python_asgi_http.c @@ -362,16 +362,6 @@ nxt_py_asgi_http_response_body(nxt_py_asgi_http_t *http, PyObject *dict) Py_ssize_t body_len, body_off; nxt_py_asgi_ctx_data_t *ctx_data; - body = PyDict_GetItem(dict, nxt_py_body_str); - if (nxt_slow_path(body != NULL && !PyBytes_Check(body))) { - return PyErr_Format(PyExc_TypeError, "'body' is not a byte string"); - } - - more_body = PyDict_GetItem(dict, nxt_py_more_body_str); - if (nxt_slow_path(more_body != NULL && !PyBool_Check(more_body))) { - return PyErr_Format(PyExc_TypeError, "'more_body' is not a bool"); - } - if (nxt_slow_path(http->complete)) { return PyErr_Format(PyExc_RuntimeError, "Unexpected ASGI message 'http.response.body' " @@ -382,9 +372,26 @@ nxt_py_asgi_http_response_body(nxt_py_asgi_http_t *http, PyObject *dict) return PyErr_Format(PyExc_RuntimeError, "Concurrent send"); } + more_body = PyDict_GetItem(dict, nxt_py_more_body_str); + if (nxt_slow_path(more_body != NULL && !PyBool_Check(more_body))) { + return PyErr_Format(PyExc_TypeError, "'more_body' is not a bool"); + } + + body = PyDict_GetItem(dict, nxt_py_body_str); + if (body != NULL) { - body_str = PyBytes_AS_STRING(body); - body_len = PyBytes_GET_SIZE(body); + if (PyBytes_Check(body)) { + body_str = PyBytes_AS_STRING(body); + body_len = PyBytes_GET_SIZE(body); + + } else if (PyByteArray_Check(body)) { + body_str = PyByteArray_AS_STRING(body); + body_len = PyByteArray_GET_SIZE(body); + + } else { + return PyErr_Format(PyExc_TypeError, + "'body' is not a byte string or bytearray"); + } nxt_unit_req_debug(http->req, "asgi_http_response_body: %d, %d", (int) body_len, (more_body == Py_True) ); diff --git a/test/python/body_bytearray/asgi.py b/test/python/body_bytearray/asgi.py new file mode 100644 index 00000000..6d2f402f --- /dev/null +++ b/test/python/body_bytearray/asgi.py @@ -0,0 +1,20 @@ +async def application(scope, receive, send): + assert scope['type'] == 'http' + + body = b'' + while True: + m = await receive() + body += m.get('body', b'') + if not m.get('more_body', False): + body = bytearray(body) + break + + await send( + { + 'type': 'http.response.start', + 'status': 200, + 'headers': [(b'content-length', str(len(body)).encode())], + } + ) + + await send({'type': 'http.response.body', 'body': body}) diff --git a/test/test_asgi_application.py b/test/test_asgi_application.py index e6668b2f..226a1ed7 100644 --- a/test/test_asgi_application.py +++ b/test/test_asgi_application.py @@ -218,6 +218,14 @@ def test_asgi_application_shm_ack_handle(): assert resp['body'] == body, 'keep-alive 1' +def test_asgi_application_body_bytearray(): + client.load('body_bytearray') + + body = '0123456789' + + assert client.post(body=body)['body'] == body + + def test_asgi_keepalive_body(): client.load('mirror') |