0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>При разработке веб-приложений разработчики сталкиваются с задачами, которые нужно решать на каждом этапе обработки запроса. Например, если у нас есть несколько маршрутов, которые требуют аутентификации, или если нам нужно логировать все входящие запросы, то реализация этой логики в каждом маршруте может привести к дублированию кода и усложнению поддержки приложения. Это также увеличивает вероятность ошибок, так как любой измененный маршрут необходимо будет обновить в нескольких местах. Использование мидлвар позволяет решить эти проблемы.</p>
1
<p>При разработке веб-приложений разработчики сталкиваются с задачами, которые нужно решать на каждом этапе обработки запроса. Например, если у нас есть несколько маршрутов, которые требуют аутентификации, или если нам нужно логировать все входящие запросы, то реализация этой логики в каждом маршруте может привести к дублированию кода и усложнению поддержки приложения. Это также увеличивает вероятность ошибок, так как любой измененный маршрут необходимо будет обновить в нескольких местах. Использование мидлвар позволяет решить эти проблемы.</p>
2
<p>Мидлвара - это функции, которые обрабатывают запросы и ответы в веб-приложениях. Они выполняются между получением запроса от клиента и отправкой ответа. Они могут выполнять различные задачи, такие как проверка прав доступа, логирование или преобразование данных в ответе</p>
2
<p>Мидлвара - это функции, которые обрабатывают запросы и ответы в веб-приложениях. Они выполняются между получением запроса от клиента и отправкой ответа. Они могут выполнять различные задачи, такие как проверка прав доступа, логирование или преобразование данных в ответе</p>
3
<p>В этом уроке мы рассмотрим, как создавать и использовать мидлвары в Flask, а также изучим примеры их применения</p>
3
<p>В этом уроке мы рассмотрим, как создавать и использовать мидлвары в Flask, а также изучим примеры их применения</p>
4
<h2>Оборачивание</h2>
4
<h2>Оборачивание</h2>
5
<p>Прежде чем перейти к изучению непосредственно мидлвар, разберем их принцип действия на примере обычных функций.</p>
5
<p>Прежде чем перейти к изучению непосредственно мидлвар, разберем их принцип действия на примере обычных функций.</p>
6
<p>Представим, что у нас есть функция, которая прибавляет 5 к аргументу:</p>
6
<p>Представим, что у нас есть функция, которая прибавляет 5 к аргументу:</p>
7
<p>Наша задача расширить возможности этой функции, при этом не меняя саму функцию. Например, мы хотим прибавлять 5 к удвоенному значению аргумента. Чтобы решить эту задачу, мы можем написать новую функцию, которая будет внутри себя использовать уже существующую функцию:</p>
7
<p>Наша задача расширить возможности этой функции, при этом не меняя саму функцию. Например, мы хотим прибавлять 5 к удвоенному значению аргумента. Чтобы решить эту задачу, мы можем написать новую функцию, которая будет внутри себя использовать уже существующую функцию:</p>
8
<p>Точно так же мы можем расширить и вторую функцию:</p>
8
<p>Точно так же мы можем расширить и вторую функцию:</p>
9
<p>В общем случае расширение функции выглядит так:</p>
9
<p>В общем случае расширение функции выглядит так:</p>
10
<p>Чтобы расширить поведение функции, нужно создать новую функцию, которая будет использовать исходную. Главное условие - интерфейсы, то есть сигнатуры, обеих функций должны совпадать. Тогда мы можем заменить в коде вызов одной функции на вызов другой, обернутой, и код продолжит работать без изменений, поскольку интерфейс остался прежним. Код, использующий новую функцию, не заметит, что он обернут и его не потребуется переписывать. Этот подход также называется декорированием.</p>
10
<p>Чтобы расширить поведение функции, нужно создать новую функцию, которая будет использовать исходную. Главное условие - интерфейсы, то есть сигнатуры, обеих функций должны совпадать. Тогда мы можем заменить в коде вызов одной функции на вызов другой, обернутой, и код продолжит работать без изменений, поскольку интерфейс остался прежним. Код, использующий новую функцию, не заметит, что он обернут и его не потребуется переписывать. Этот подход также называется декорированием.</p>
11
<p>По похожей идее работают мидлвары. Они расширяют функционал обработчиков запросов, оборачивая их в подобные методы. При этом оригинальный обработчик остается неизменным.</p>
11
<p>По похожей идее работают мидлвары. Они расширяют функционал обработчиков запросов, оборачивая их в подобные методы. При этом оригинальный обработчик остается неизменным.</p>
12
<h2>Использование мидлвар</h2>
12
<h2>Использование мидлвар</h2>
13
<p>Чтобы использовать мидлвары в Flask, не нужно ничего устанавливать, фреймворк имеет встроенную поддержку мидлвар. Для добавления мидлвар используются декораторы @before_request или @after_request. Декоратор @before_request используется для указания кода, который должен быть выполнен до запроса, а @after_request - после.</p>
13
<p>Чтобы использовать мидлвары в Flask, не нужно ничего устанавливать, фреймворк имеет встроенную поддержку мидлвар. Для добавления мидлвар используются декораторы @before_request или @after_request. Декоратор @before_request используется для указания кода, который должен быть выполнен до запроса, а @after_request - после.</p>
14
<p>Рассмотрим пример кода с подключением мидлвары:</p>
14
<p>Рассмотрим пример кода с подключением мидлвары:</p>
15
<p>В приведенном примере подключена мидлвара, которая для каждого входящего запроса выводит в консоль сообщение с указанием пути. Также добавлена мидлвара, которая выполняется после обработки запроса и выводит в консоль сообщение, информируя о том, что ответ был успешно отправлен клиенту. Во Flask в мидлваре @after_request обязательно нужно вернуть объект response.</p>
15
<p>В приведенном примере подключена мидлвара, которая для каждого входящего запроса выводит в консоль сообщение с указанием пути. Также добавлена мидлвара, которая выполняется после обработки запроса и выводит в консоль сообщение, информируя о том, что ответ был успешно отправлен клиенту. Во Flask в мидлваре @after_request обязательно нужно вернуть объект response.</p>
16
<p>Каждый раз, когда мы используем @before_request или @after_request, очередная мидлвара добавляется в общую цепочку. Каждый запрос, отправляемый на обработку в приложение, проходит через всю цепочку этих мидлвар</p>
16
<p>Каждый раз, когда мы используем @before_request или @after_request, очередная мидлвара добавляется в общую цепочку. Каждый запрос, отправляемый на обработку в приложение, проходит через всю цепочку этих мидлвар</p>
17
<p>Flask по умолчанию выполняет все before мидлвары по порядку, как они заданы в коде. Но если какая-то из них возвращает значение, то на ней закончится вызов, и вернется response.</p>
17
<p>Flask по умолчанию выполняет все before мидлвары по порядку, как они заданы в коде. Но если какая-то из них возвращает значение, то на ней закончится вызов, и вернется response.</p>
18
<p>Если же ни одна из before мидлвар не совершила return, то выполнение дойдет до обработчика маршрута.</p>
18
<p>Если же ни одна из before мидлвар не совершила return, то выполнение дойдет до обработчика маршрута.</p>
19
<p>Затем, в конце, выполнится after мидлвара.</p>
19
<p>Затем, в конце, выполнится after мидлвара.</p>
20
<p>В примере выше мы подключили мидлвары, одна из которых выводит в консоль сообщение, а другая добавляет кастомный заголовок<em>X-Custom-Header</em>в каждый ответ.</p>
20
<p>В примере выше мы подключили мидлвары, одна из которых выводит в консоль сообщение, а другая добавляет кастомный заголовок<em>X-Custom-Header</em>в каждый ответ.</p>
21
<p>Запустим сервер и сделаем запрос:</p>
21
<p>Запустим сервер и сделаем запрос:</p>
22
<p>При этом в консоли, где запущено приложение, мы можем увидеть вывод:</p>
22
<p>При этом в консоли, где запущено приложение, мы можем увидеть вывод:</p>
23
<h2>Обработчики</h2>
23
<h2>Обработчики</h2>
24
<p>Самое интересное в мидлварах, что обработчики конкретных маршрутов - это тоже мидлвары. Но в отличие от мидлвар, которые выполняются для всех запросов, обработчики привязаны к конкретному маршруту.</p>
24
<p>Самое интересное в мидлварах, что обработчики конкретных маршрутов - это тоже мидлвары. Но в отличие от мидлвар, которые выполняются для всех запросов, обработчики привязаны к конкретному маршруту.</p>
25
<h2>Терминальная мидлвара</h2>
25
<h2>Терминальная мидлвара</h2>
26
<p>Далеко не всегда мы хотим двигаться вглубь по всей цепочке добавленных мидлвар. Например, хотим создать мидлвару для проверки наличия определенного параметра в запросе, не меняя при этом сам обработчик. Если параметр отсутствует, мы можем сразу отправить ответ с ошибкой и пропустить выполнение остальных мидлвар и обработчиков. В таком случае нам нужно сделать return в мидлваре. После возврата движение по цепочке прекратится, все оставшиеся мидлвары пропускаются и происходит отправка ответа:</p>
26
<p>Далеко не всегда мы хотим двигаться вглубь по всей цепочке добавленных мидлвар. Например, хотим создать мидлвару для проверки наличия определенного параметра в запросе, не меняя при этом сам обработчик. Если параметр отсутствует, мы можем сразу отправить ответ с ошибкой и пропустить выполнение остальных мидлвар и обработчиков. В таком случае нам нужно сделать return в мидлваре. После возврата движение по цепочке прекратится, все оставшиеся мидлвары пропускаются и происходит отправка ответа:</p>
27
<p>У такого поведения, когда есть цепочка функций и любая из них в процессе обработки может принять решение остановки цепочки и возврата ответа, есть имя. Такие цепочки называют<a>chain responsibility</a>, и это тоже паттерн</p>
27
<p>У такого поведения, когда есть цепочка функций и любая из них в процессе обработки может принять решение остановки цепочки и возврата ответа, есть имя. Такие цепочки называют<a>chain responsibility</a>, и это тоже паттерн</p>
28
<p>Помимо этого существует мидлвары выполнямые после отправки ответа - teardown_request(). Эта мидлвара выполнится даже в случае, если во время выполнения программы сгенерируется и не будет обработано исключение.</p>
28
<p>Помимо этого существует мидлвары выполнямые после отправки ответа - teardown_request(). Эта мидлвара выполнится даже в случае, если во время выполнения программы сгенерируется и не будет обработано исключение.</p>
29
<p>В консоли, где запущено приложение, мы можем увидеть, что сообщение из мидлвары все равно выведется, и лишь затем будет стектрейс ошибки:</p>
29
<p>В консоли, где запущено приложение, мы можем увидеть, что сообщение из мидлвары все равно выведется, и лишь затем будет стектрейс ошибки:</p>
30
30