Персональный
сайт
Игоря
Сысоева



sysoev.ru
mod_accel
mod_deflate
программирование
windows
freebsd
apache
pppd
unix
web

для писем

Почему невозможно корректно ограничить размер закачиваемого файла

 

09.03.2002

Иногда нужно ограничить размер закачиваемого файла. Казалось бы, сделать это достаточно просто – в заголовке "Content-Length" браузер сообщает размер тела запроса. Если этот размер больше нашего ограничения, то возвращаем браузеру ошибку "413 Request Entity Too Large" и закрываем соединение. Однако всё осложняется тем фактом, что MSIE 4.x-6.x и Netscape 4.x считают, что ответ от сервера может быть получен только после того, как они полностью передадут запрос. Если соединение закрывается во время передачи запроса, то вместо переданного сервером сообщения об ошибке MSIE показывает стандартное сообщение "This page cannot be displayed", а Netscape 4.x – "A network error occurred while Netscape was sending data (Network Error: Broken pipe)", и в результате понять, что именно послужило причиной ошибки, невозможно. Точно также ведут себя Opera и Konqueror. А вот Mozilla и Netscape 6.x в такой ситуации работают корректно и показывают переданное сообщение об ошибке.

В Apache эта проблема частично решается с помощью медленного закрытия (lingering close) соединения. Когда соединение необходимо закрыть, Apache вызывает shutdown() для сокета с параметром SHUT_WR, тем самым сообщая браузеру о том, что больше он ничего передавать не будет. После этого Apache в течение 2 секунд ждёт, не передаст ли ему что-нибудь браузер. Если что-то передано, Apache считывает это, никуда не сохраняя, и снова в цикле ждёт 2 секунды. Если в течение 2 секунд ничего не передавалось, то Apache закрывает соединение. Максимальное время ожидания задаётся при сборке Apache с помощью переменной MAX_SECS_TO_LINGER, по умолчанию равной 30 секундам. По истечении этого времени Apache закрывает соединение, даже если браузер не завершил передачу. Таким образом, если установленно ограничение на размер закачиваемого файла, то браузер покажет сообщение о 413 ошибке только в том случае, если он успеет в течение 30 секунд передать полностью запрос. Например, модемный пользователь, для которого наиболее критично ограничивать размеры, со скоростью 3K/s за 30 секунд успеет передать около 100K.

Необходимо заметить, что ограничение размера числом больше 1M будет работать не всегда. Дело в том, что около 20% всех запросов выполняется через прокси-сервера Squid, в которых по умолчанию стоит ограничение на 1M (директива request_body_max_size) и его очень редко меняют. В отличие от Apache Squid после передачи сообщения о 413 ошибке сразу же закрывает соединение.

В стандарте HTTP/1.1 для закачивания файлов предусмотрен заголовок браузера "Expect: continue", в ответ на который сервер может вернуть сообщение об ошибке или же ответить кодом "HTTP/1.1 100 Continue", после чего браузер может передавать тело запроса. Однако ни один из современных броузеров это не поддерживает.

(C) Igor Sysoev
http://sysoev.ru