Сброс TCP-соединения происходит, когда приложение WSGI отвечает перед использованием среды ['wsgi.input']
Для нашего веб-сервиса я написал логику, чтобы предотвратить multipart/form-data
POST больше, чем, скажем, 4mb.
Это сводится к следующему (я отбросил все использование WebOb и просто уменьшил его до простого ванильного кода WSGI):
import paste.httpserver
form = """\
<html>
<body>
<form method="post" enctype="multipart/form-data" action="/">
<input type="file" name="photopicker" />
<input type="submit" />
</form>
</body>
</html>
"""
limit = 4 * 1024 * 1024
def upload_app(environ, start_response):
if environ['REQUEST_METHOD'] == 'POST':
if int(environ.get('CONTENT_LENGTH', '0')) > limit:
start_response('400 Ouch', [('content-type', 'text/plain')])
return ["Upload is too big!"]
# elided: consume the file appropriately
start_response('200 OK', [('content-type', 'text/html')])
return [form]
paste.httpserver.serve(upload_app, port=7007)
Показанная логика работает правильно при тестировании модуля. Но как только я попытался отправить фактические файлы размером более 4 МБ в эту конечную точку, я получил такие ошибки на стороне клиента:
Error 101 (net::ERR_CONNECTION_RESET): Unknown error.
из Google ChromeThe connection to the server was reset while the page was loading.
от Firefox
Та же ошибка возникает при использовании встроенного Python wsgiref
HTTP-сервер.
Факт: однажды я добавил environ['wsgi.input'].read()
Непосредственно перед ответом по HTTP 400 проблема сброса соединения исчезла. Конечно, это не очень хорошее решение. Это просто показывает, что происходит, когда вы полностью потребляете ввод.
Я изучил HTTP: "Полное руководство" и нашел несколько интересных рекомендаций о том, как важно тщательно управлять TCP-соединениями при реализации HTTP-серверов и клиентов. Это продолжалось о том, как вместо close
-н розетку, было предпочтительнее делать shutdown
, чтобы у клиента была возможность среагировать и прекратить отправку дополнительных данных на сервер.
Возможно, мне не хватает некоторых важных деталей реализации, которые предотвращают такие сбросы соединения. Кто-нибудь прозрения?
Смотрите суть.
1 ответ
Это происходит потому, что вы отбрасываете входной поток, не читая его, и это заставляет его закрыться. Браузер поставил в очередь большую часть файла для отправки, и затем он получает ошибку записи, потому что сервер принудительно закрывает соединение.
Я не знаю, как обойти это, не прочитав все входные данные.
Я бы порекомендовал немного Javascript для проверки размера файла перед его отправкой. Тогда единственными людьми, которые получают ошибку, являются те, кто игнорирует проверку на стороне клиента, потому что у них нет Javascript или потому что они намеренно пытаются быть вредоносными.