(Обновлено, потому что я понял, что пытался исправить это, поэтому меня смутила исходная проблема и проблема, которая заставила меня сдаться)
Я делаю частичный запрос к приложению, которое использует Werkzeug (текущий мастер git). get_input_stream завершает вызов LimitedStream(wsgi.input, min(content_length, max_content_length))
. min(content_length, max_content_length)
всегда будет None при использовании кодирования по фрагментам.
Пытаясь добиться прогресса, я попытался использовать LimitedStream(stream, content_length or max_content_length)
, но затем я получил исключение ClientDisconnected
, потому что мы не можем сказать разницу между отключением клиента и простым выполнением фрагментированного запроса. , поскольку wsgi.input.read()
в обоих случаях просто возвращает строку нулевой длины.
Это больше, чем просто ошибка с min
. После исправления проблема заключается в том, что выполнение wsgi.input.read(max_content_length)
с блоками Werkzeug навсегда, если для чтения меньше max_content_length
. Или при использовании Gunicorn, который поддерживает фрагменты путем синтаксического анализа и буферизации всего сообщения, длина оказывается меньше max_content_length
, поэтому LimitedStream
считает, что клиент отключился.
Я протестировал это на Django, чтобы убедиться, что мы не делаем чего-то странного, он тоже видит пустой поток.
Самый простой путь вперед - предоставить промежуточное программное обеспечение, которое устанавливает environ['wsgi.input_terminated']
и говорит людям использовать его при использовании сервера, поддерживающего частичную передачу.
Какой wsgi в настоящее время поддерживает input_terminated
? После того, как весь день прожиг на отладке, почему данные пусты, почему поток пуст, а затем понял, что это из-за кодирования потокового потока, я теперь не могу найти ничего, что поддерживает это: /
Должны ли мы не только проверять environ.get('wsgi.input_terminated')
также проверять environ.get('HTTP_TRANSFER_ENCODING') == 'chunked'
и в этом случае также напрямую возвращать развернутый поток? Это устраняет такие проблемы, как простой curl -H 'Transfer-Encoding: chunked' ...
возвращающий пустой поток.
Согласно RFC2616
4.4.2
Если поле заголовка Transfer-Encoding (раздел 14.41) присутствует и
имеет любое значение, кроме "identity", тогда длина передачи равна
определяется с помощью "фрагментированного" кодирования передачи (раздел 3.6),
если сообщение не прерывается закрытием соединения.
4.4.3
Если поле заголовка Content-Length (раздел 14.13) присутствует, его
десятичное значение в OCTET представляет как длину объекта, так и
длина передачи. Поле заголовка Content-Length НЕ ДОЛЖНО отправляться
если эти две длины различаются (например, если Transfer-Encoding
поле заголовка присутствует). Если сообщение получено с обоими
Поле заголовка Transfer-Encoding и поле заголовка Content-Length,
последнее ДОЛЖНО игнорироваться.
... отмечая, что Transfer-Encoding
из chunked
требует, чтобы любой заголовок Content-Length
игнорировался, и поэтому на его основе не должна выполняться потоковая обработка. В настоящее время это так, если не задано значение wsgi.input_terminated
.
Должно ли действительно быть необходимо установить wsgi.input_terminated
для нормальной работы кодирования фрагментов, например, 10-байтовой полезной нагрузки JSON?
Самый полезный комментарий
Какой wsgi в настоящее время поддерживает
input_terminated
? После того, как весь день прожиг на отладке, почему данные пусты, почему поток пуст, а затем понял, что это из-за кодирования потокового потока, я теперь не могу найти ничего, что поддерживает это: /