Сброс TCP-соединения происходит, когда приложение WSGI отвечает перед использованием environ['wsgi.input']

StackOverflow https://stackoverflow.com/questions/2099752

Вопрос

Для нашего веб-сервиса я написал некоторую логику, чтобы предотвратить multipart/form-data POST-сообщения размером, скажем, более 4 МБ.

Это сводится к следующему (я удалил все использование 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 Chrome
  • The 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-ing сокет, было предпочтительнее сделать shutdown, чтобы клиент имел возможность отреагировать и прекратить отправку дополнительных данных на сервер.

Возможно, мне не хватает какой-то важной детали реализации, которая предотвращает такой сброс соединения.Есть идеи?

Видеть суть.

Это было полезно?

Решение

Это происходит потому, что вы отбрасываете входной поток, не читая его, и это приводит к его принудительному закрытию.Браузер уже поставил в очередь значительную часть файла для отправки, а затем получает ошибку записи, поскольку сервер принудительно закрывает соединение.

Я не знаю способа обойти это, не прочитав всю входную информацию.

Я бы порекомендовал Javascript для проверки размера файла перед его отправкой.Тогда единственные люди, которые получают ошибку, — это те, кто игнорирует проверку на стороне клиента, потому что у них нет Javascript или потому, что они намеренно пытаются быть вредоносными.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top