HTML Diff
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