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
This commit is contained in:
Benoit Chesneau 2026-03-24 23:17:51 +01:00 committed by GitHub
parent f555180191
commit 385a9211e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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.