From 385a9211e2e2df33a7cea4b27b18938bc0eb8b70 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Tue, 24 Mar 2026 23:17:51 +0100 Subject: [PATCH] Fix uwsgi incomplete header error with async workers (#3554) The _read_exact method was calling unreader.read() without a size parameter, which only reads one chunk at a time. With gevent/gthread workers, this could return incomplete data before the full header arrived. Use unreader.read(size) which has proper retry logic built-in to read the exact number of bytes requested. Fixes #3552 --- gunicorn/uwsgi/message.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/gunicorn/uwsgi/message.py b/gunicorn/uwsgi/message.py index 3a5aca18..48a3fd75 100644 --- a/gunicorn/uwsgi/message.py +++ b/gunicorn/uwsgi/message.py @@ -2,8 +2,6 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. -import io - from gunicorn.http.body import LengthReader, Body from gunicorn.uwsgi.errors import ( InvalidUWSGIHeader, @@ -117,23 +115,7 @@ class UWSGIRequest: def _read_exact(self, unreader, size): """Read exactly size bytes from the unreader.""" - buf = io.BytesIO() - remaining = size - - while remaining > 0: - data = unreader.read() - if not data: - break - buf.write(data) - remaining = size - buf.tell() - - result = buf.getvalue() - # Put back any extra bytes - if len(result) > size: - unreader.unread(result[size:]) - result = result[:size] - - return result + return unreader.read(size) def _parse_vars(self, data): """Parse uWSGI vars block into key-value pairs.