Skip to content

Commit 3fea47e

Browse files
committed
python: Add Django 5.x compatibility
Note: This may not be *specific* to Django 5.x but is where the issue showed up. @codedoga on GitHub reported an issue with Unit and Django 5.x When trying to perform a simple POST/PUT request with body data, Unit was throwing the following error 2025/02/16 11:07:14 [error] 6#6 [unit] #9: Python failed to call 'future.result()' Traceback (most recent call last): File "/usr/local/lib/python3.13/site-packages/django/core/handlers/asgi.py", line 162, in __call__ await self.handle(scope, receive, send) File "/usr/local/lib/python3.13/site-packages/django/core/handlers/asgi.py", line 208, in handle task.result() ~~~~~~~~~~~^^ File "/usr/local/lib/python3.13/site-packages/django/core/handlers/asgi.py", line 239, in listen_for_disconnect assert False, "Invalid ASGI message after request body: %s" % message["type"] ^^^^^ AssertionError: Invalid ASGI message after request body: http.request There is no such issue with Django 4.x The issue was caused when Django started doing an 'async receive()' just after we have handled the initial request and passed it to the application. Django is then looking to see if/when we send it a 'http.disconnect' message. We were not prepared for this and would go through all the motions of handling the request again which would result in the erroneous 'http.request' message. What we need to do is track when we've handled the initial request. We can then use that information coupled with the fact if we get a request with 0 content length then we basically have nothing to do. For this we create a new nxt_py_asgi_http_t member, request_received. We can repurpose 'empty_body_received' for this if we rename it and change where we set it as now if 'request_received' is true then so would 'empty_body_received'. 'empty_body_received' was actually part of a previous commit that was addressing various receive() issues. I've checked that the provided reproducer application still works. Link: <django/django@1d1ddff> Link: <#564> Fixes: 5675452 ("Python: fixing ASGI receive() issues.") Closes: #1561 Signed-off-by: Andrew Clayton <[email protected]>
1 parent 7a0addd commit 3fea47e

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

src/python/nxt_python_asgi_http.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ typedef struct {
2727
Py_ssize_t send_body_off;
2828
uint8_t complete;
2929
uint8_t closed;
30-
uint8_t empty_body_received;
30+
uint8_t request_received;
3131
} nxt_py_asgi_http_t;
3232

3333

@@ -102,7 +102,7 @@ nxt_py_asgi_http_create(nxt_unit_request_info_t *req)
102102
http->send_body_off = 0;
103103
http->complete = 0;
104104
http->closed = 0;
105-
http->empty_body_received = 0;
105+
http->request_received = 0;
106106
}
107107

108108
return (PyObject *) http;
@@ -177,11 +177,9 @@ nxt_py_asgi_http_read_msg(nxt_py_asgi_http_t *http)
177177
}
178178

179179
if (size == 0) {
180-
if (http->empty_body_received) {
180+
if (http->request_received) {
181181
Py_RETURN_NONE;
182182
}
183-
184-
http->empty_body_received = 1;
185183
}
186184

187185
if (size > 0) {
@@ -234,6 +232,8 @@ nxt_py_asgi_http_read_msg(nxt_py_asgi_http_t *http)
234232

235233
Py_XDECREF(body);
236234

235+
http->request_received = 1;
236+
237237
return msg;
238238
}
239239

0 commit comments

Comments
 (0)