2015-05-03 2 views
2

Когда django развернут на apache с mod_wsgi. Кажется, он обрабатывает неполные или отмененные запросы очень странным образом.Django/apache handle неполный/отменен HTTP-запросы

Если клиент отменяет запрос, отмененный запрос не отменяется на django, например, если вы загружаете большой файл, очевидно, что тело запроса будет фактически передано, поэтому, когда django читает тело, и клиент отменяет запрос, он все еще обрабатывается (просто неполным), и действие аннулирования фактического запроса никогда не замечается.

Это один пример журнала из apache, когда запрос отменен. [Пт май 01, 22: 05: 51.055968 2015] [: error] [pid 31609] (70008) Частичные результаты действительны, но обработка неполна: [клиент 172.31.43.91:3645] mod_wsgi (pid = 31609): не удается получить ведро бригады для запроса.

Затем, если код django не был создан (потому что запрос неполный, но он прибывает в django и обрабатывается так, как если бы он имел данные), и поэтому django будет терпеть неудачу при попытке получить данные (и возвращать отсутствующие ошибки поля XX, или то, что когда-либо делает логика для их обработки)

Наконец, когда django пытается ответить на ответ, он, очевидно, потерпит неудачу, а клиент уже закрыл соединение.

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

Полный журнал, когда это произойдет, будет выглядеть примерно так:

[Пт Май 01 22: 05: 51,055968 2015] [: ошибка] [PID 31609] (70008) Частичные результаты справедливы, но обработка является неполным : [клиент 172.31.43.91:3645] mod_wsgi (pid = 31609): Невозможно получить ведро-бригаду для запроса.

[Пт 1 Май 22: 05: 51,062690 2015] [: ошибка] [PID 10580] некоторые сообщения об ошибке, связанные с отсутствием данных здесь

[Пт 1 Май 22: 05: 51,068790 2015] [: ошибка] [pid 10580] [remote 172.31.43.91:0] mod_wsgi (pid = 10580): Исключение произошло при обработке сценария WSGI «some-path/wsgi.py».

[Пт 1 Май 22: 05: 51,068827 2015] [: ошибка] [PID 10580] [удаленный 172.31.43.91:0] IOError: не удалось записать данные

Теперь последний вопрос, есть ли способ обнаружить такой неполный запрос и обработать его соответствующим образом, а не просто потерпеть неудачу позже с отсутствием требуемых данных?

ответ

3

При чтении содержимого запроса, если требуемая длина содержимого не была прочитана, тогда WSGI-уровень будет, когда wsgi.input.read() был вызван, вызывает исключение IOError. Это может быть передано как в Django, либо в более поздних версиях должно быть изменено на другой тип исключения IOError, который называется UnreadablePostError.

Когда ваш код приложения специально не проверяет наличие сломанного содержимого запроса и не обрабатывает этот тип исключения, он распространяет резервную копию и обрабатывается Django как незащищенное исключение. В этот момент Django попытается написать ответ об ошибке 500. Когда это будет написано на уровне WSGI, он будет терпеть неудачу, поскольку соединение было закрыто, что может быть обнаружено только при попытке написать ответ.

Поэтому Django не должен давать вам неполные данные POST, и вместо этого должно быть исключение.

Относительно того, есть ли лучший способ обращения с ним, ответ отрицательный. Поскольку спецификация WSGI основана на блокирующей модели, обнаружение и обработка сброшенных соединений в чистом виде на самом деле невозможно. Нужно переключиться на веб-сервер и инфраструктуру ASYNC, чтобы иметь возможность лучше обрабатывать его, а это значит, что вы не можете использовать WSGI или Django.

FWIW, были обсуждены проблемы сброшенных соединений в списке рассылки mod_wsgi. Поэтому вы можете перейти в группы Google и выполнить поиск в архиве списка, используя условия поиска, такие как «сброшенное соединение» или «неудачное соединение» или «закрытое соединение», и посмотреть, что вы можете найти.

+0

При чтении запроса исключение не исключение, поскольку мой код «просмотр (или контроллер)» выполняется нормально, поэтому я могу регистрировать много вещей, когда это происходит. Итак, где я должен смотреть на это исключение? Это очень помогло бы мне обнаружить неполные запросы ... – user1777914

+0

Какую версию Django вы используете? Какая версия mod_wsgi? Если вы используете старую версию mod_wsgi, я предлагаю обновить ее до последней версии и посмотреть, будут ли вещи вести себя по-другому, особенно если вы используете режим демонов mod_wsgi. –

+0

Django 1.7.7, mod_wsgi 3.5 python 2.7.8. Я считаю, что исключение не возникает, потому что фактическая загрузка не является файлом (или многочастной формой), а вместо этого формой с кодированным образцом base65 в виде строки, поэтому она не входит в фактический объект request.FILES, но вместо этого в request.POST. Я считаю, что исключение только для файлов? – user1777914