Обработка данных запроса
Самое важное правило веб-разработки — «Не доверяйте пользователю». Это особенно актуально для данных входящих запросов на входе. С WSGI это на самом деле немного сложнее, чем вы ожидаете. Поэтому Werkzeug оборачивает поток запроса для вас, чтобы спасти вас от наиболее распространенных проблем с ним.
Отсутствие маркера EOF в потоке ввода
Поток ввода не имеет маркера конца файла. Если бы вы вызвали метод read() в потоке wsgi.input, вы бы заставили ваше приложение зависнуть на серверах, соответствующих стандарту. На самом деле это сделано намеренно, хотя и неприятно. Werkzeug решает эту проблему, обернув поток ввода в специальный LimitedStream. Поток ввода доступен в объектах запроса как stream. Он либо пустой поток (если данные формы были обработаны), либо ограниченный поток с содержимым потока ввода.
Когда Werkzeug обрабатывает?
Werkzeug обрабатывает входящие данные в следующих ситуациях:
- вы обращаетесь к
form,files, илиstreamи метод запроса былPOSTилиPUT. - если вы вызываете
parse_form_data().
Эти вызовы не взаимозаменяемы. Если вы вызываете parse_form_data(), вы не должны использовать объект запроса или, по крайней мере, не атрибуты, которые запускают процесс обработки.
Это также верно, если вы читаете из потока wsgi.input перед обработкой.
Общее правило: оставьте поток ввода WSGI в покое. Особенно в WSGI-средствах. Используйте либо функции обработки, либо объект запроса. Не смешивайте несколько библиотек WSGI для обработки данных формы или чего-либо другого, что работает с потоком ввода.
Как происходит обработка?
Стандартное поведение обработки Werkzeug обрабатывает три случая:
- тип содержимого ввода был
multipart/form-data. В этой ситуацииstreamбудет пустым, аformбудет содержать обычные данныеPOST/PUT,filesбудет содержать загруженные файлы в виде объектовFileStorage. - тип содержимого ввода был
application/x-www-form-urlencoded. Тогдаstreamбудет пустым, аformбудет содержать обычные данныеPOST/PUT, иfilesбудет пустым. - тип содержимого ввода не был ни тем, ни другим,
streamуказывает наLimitedStreamс данными ввода для дальнейшей обработки.
Особое замечание по методу get_data: Вызов этого метода загружает все данные запроса в память. Это безопасно только в том случае, если установлено значение max_content_length. Также вы можете либо прочитать поток, либо вызвать get_data().
Ограничение данных запроса
Класс Request предоставляет несколько атрибутов для управления тем, сколько данных из тела запроса обрабатывается. Это может помочь уменьшить атаки типа DoS, которые создают запрос таким образом, что сервер использует слишком много ресурсов для его обработки. Каждое из этих ограничений вызовет RequestEntityTooLarge, если они будут превышены.
-
max_content_lengthПрекратить чтение данных запроса после этого количества байт. Лучше настроить это на WSGI-сервере или HTTP-сервере, а не в WSGI-приложении. -
max_form_memory_sizeПрекратить чтение данных запроса, если какая-либо часть формы больше этого количества байт. В то время как части файлов могут быть перемещены на диск, обычные данные полей формы хранятся только в памяти. -
max_form_partsПрекратить чтение данных запроса, если в данных multipart-формы отправлено более этого количества частей. Это полезно для остановки очень большого количества очень маленьких частей, особенно частей файлов. По умолчанию значение равно 1000.
Использование Werkzeug для установки этих ограничений — это только один уровень защиты. WSGI-серверы и HTTPS-серверы должны устанавливать свои собственные ограничения по размеру и таймаутам. Операционная система или менеджер контейнеров должны устанавливать ограничения на память и время обработки для процессов сервера.
Если ошибка 413 Content Too Large возвращается до того, как весь запрос будет прочитан, клиенты могут вместо ошибки 413 показать ошибку «разрыв соединения». Это зависит от того, как WSGI/HTTP-сервер и клиент обрабатывают соединения, это не то, над чем WSGI-приложение (Werkzeug) имеет контроль.
Как расширить обработку?
Современные веб-приложения передают гораздо больше, чем данные multipart-формы или данные url-кодирования. Чтобы расширить возможности, подклассируйте Request или Request и добавьте или расширьте методы.
© 2007 Pallets
Licensed under the BSD 3-clause License.
https://werkzeug.palletsprojects.com/en/3.0.x/request_data/