HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>В веб-приложениях часто есть логика, которая должна выполняться перед обработкой любого запроса. К такой логике относятся: проверка доступа, логирование запроса, ограничение количества запросов. Перед веб-разработчиками часто встает проблема в организации такой логики, чтобы разрабатывать без сложностей и поддерживать приложение.</p>
1 <p>В веб-приложениях часто есть логика, которая должна выполняться перед обработкой любого запроса. К такой логике относятся: проверка доступа, логирование запроса, ограничение количества запросов. Перед веб-разработчиками часто встает проблема в организации такой логики, чтобы разрабатывать без сложностей и поддерживать приложение.</p>
2 <p>Чтобы решить эту проблему, в веб-приложениях используются посредники, которые выполняются перед обработчиками HTTP-запросов. В этом уроке мы научимся использовать посредников в микрофреймворке Fiber и разберем конкретные примеры реализации.</p>
2 <p>Чтобы решить эту проблему, в веб-приложениях используются посредники, которые выполняются перед обработчиками HTTP-запросов. В этом уроке мы научимся использовать посредников в микрофреймворке Fiber и разберем конкретные примеры реализации.</p>
3 <h2>Middlewares</h2>
3 <h2>Middlewares</h2>
4 <p>Посредники или middlewares в Fiber являются функциями func(c *fiber.Ctx) error, которые мы устанавливаем перед обработчиками. Посредник может изменять запрос, добавлять заголовки, выполнять логирование. Посредник также может прервать цепочку обработки запроса, если возникла ошибка.</p>
4 <p>Посредники или middlewares в Fiber являются функциями func(c *fiber.Ctx) error, которые мы устанавливаем перед обработчиками. Посредник может изменять запрос, добавлять заголовки, выполнять логирование. Посредник также может прервать цепочку обработки запроса, если возникла ошибка.</p>
5 <p>Пример посредника, который проверяет возможность доступа пользователя к веб-приложению, может выглядеть следующим образом:</p>
5 <p>Пример посредника, который проверяет возможность доступа пользователя к веб-приложению, может выглядеть следующим образом:</p>
6 <p>В примере выше мы создали посредник accessMiddleware, который проверяет наличие корректного токена доступа в параметрах запроса. Если токен не прошел проверку, то посредник прерывает цепочку обработки запроса и возвращает клиенту статус<em>401 Unauthorized</em>. Если токен валиден, то посредник вызывает метод c.Next(), который продолжает обработку запроса.</p>
6 <p>В примере выше мы создали посредник accessMiddleware, который проверяет наличие корректного токена доступа в параметрах запроса. Если токен не прошел проверку, то посредник прерывает цепочку обработки запроса и возвращает клиенту статус<em>401 Unauthorized</em>. Если токен валиден, то посредник вызывает метод c.Next(), который продолжает обработку запроса.</p>
7 <p>Такой подход работает, когда мы хотим использовать посредника на всех обработчиков в приложении. Но бывают ситуации, когда нам нужно использовать посредник только на некоторых обработчиках.</p>
7 <p>Такой подход работает, когда мы хотим использовать посредника на всех обработчиков в приложении. Но бывают ситуации, когда нам нужно использовать посредник только на некоторых обработчиках.</p>
8 <h2>Группировка запросов в маршрутизации</h2>
8 <h2>Группировка запросов в маршрутизации</h2>
9 <p>Чтобы назначить посредника только на некоторые обработчики в Fiber, их нужно сначала сгруппировать с помощью функции r.Group(). После этого мы можем устанавливать посредников для всей группы с помощью r.Use():</p>
9 <p>Чтобы назначить посредника только на некоторые обработчики в Fiber, их нужно сначала сгруппировать с помощью функции r.Group(). После этого мы можем устанавливать посредников для всей группы с помощью r.Use():</p>
10 <p>В примере выше мы создали две группы запросов:<em>authGroup</em>и<em>publicGroup</em>. В группу<em>authGroup</em>мы добавили посредник<em>accessMiddleware</em>, который проверяет наличие корректного токена доступа в параметрах запроса. В группу<em>publicGroup</em>мы не добавили посредников, поэтому при запросах к группе сразу выполняются обработчики:</p>
10 <p>В примере выше мы создали две группы запросов:<em>authGroup</em>и<em>publicGroup</em>. В группу<em>authGroup</em>мы добавили посредник<em>accessMiddleware</em>, который проверяет наличие корректного токена доступа в параметрах запроса. В группу<em>publicGroup</em>мы не добавили посредников, поэтому при запросах к группе сразу выполняются обработчики:</p>
11 <p>Мы разобрались, как создавать своих посредников в Fiber. Но также существует набор готовых посредников, которые мы можем подключать в своих проектах. Каждый посредник представлен отдельным пакетом, который можно добавлять в проект при необходимости. Рассмотрим самые популярные из них.</p>
11 <p>Мы разобрались, как создавать своих посредников в Fiber. Но также существует набор готовых посредников, которые мы можем подключать в своих проектах. Каждый посредник представлен отдельным пакетом, который можно добавлять в проект при необходимости. Рассмотрим самые популярные из них.</p>
12 <h2>Логирование запросов</h2>
12 <h2>Логирование запросов</h2>
13 <p>Логирование необходимо для отладки работающих веб-приложений. Помимо явного логирования в местах ошибок, мы можем добавить логирование всех запросов. Так мы будем понимать, какие запросы приходят в приложение, по какому пути и с какими параметрами.</p>
13 <p>Логирование необходимо для отладки работающих веб-приложений. Помимо явного логирования в местах ошибок, мы можем добавить логирование всех запросов. Так мы будем понимать, какие запросы приходят в приложение, по какому пути и с какими параметрами.</p>
14 <p>Чтобы добавить логирование всех запросов в Fiber-приложение, нужно подключить к проекту пакет<em>github.com/gofiber/fiber/v2/middleware/logger</em>и инициализировать его перед всеми обработчиками:</p>
14 <p>Чтобы добавить логирование всех запросов в Fiber-приложение, нужно подключить к проекту пакет<em>github.com/gofiber/fiber/v2/middleware/logger</em>и инициализировать его перед всеми обработчиками:</p>
15 <p>Запускаем веб-приложение и переходим в браузере на страницу<em><a>http://localhost</a></em>. Видим, что в ответ пришло сообщение "OK". При этом в консоли веб-приложения появилось сообщение о залогированном запросе:</p>
15 <p>Запускаем веб-приложение и переходим в браузере на страницу<em><a>http://localhost</a></em>. Видим, что в ответ пришло сообщение "OK". При этом в консоли веб-приложения появилось сообщение о залогированном запросе:</p>
16 <p>Если несколько раз перезагружать страницу<em><a>http://localhost</a></em>, мы увидим несколько записей лога.</p>
16 <p>Если несколько раз перезагружать страницу<em><a>http://localhost</a></em>, мы увидим несколько записей лога.</p>
17 <p>Так мы добавили логирование всех запросов в наше веб-приложение. По умолчанию логирование происходит в консоль, но можно настроить логирование в файл или в другие системы логирования.</p>
17 <p>Так мы добавили логирование всех запросов в наше веб-приложение. По умолчанию логирование происходит в консоль, но можно настроить логирование в файл или в другие системы логирования.</p>
18 <p>Также при инициализации посредника для логирования мы можем указать формат логов, который подходит для нашего проекта. Для этого нужно передать в функцию инициализации посредника параметр logger.Config:</p>
18 <p>Также при инициализации посредника для логирования мы можем указать формат логов, который подходит для нашего проекта. Для этого нужно передать в функцию инициализации посредника параметр logger.Config:</p>
19 <p>Запускаем веб-приложение и переходим в браузере на страницу<em><a>http://localhost</a></em>. Видим, что в ответ пришло сообщение "OK". При этом в консоли веб-приложения изменился формат логов:</p>
19 <p>Запускаем веб-приложение и переходим в браузере на страницу<em><a>http://localhost</a></em>. Видим, что в ответ пришло сообщение "OK". При этом в консоли веб-приложения изменился формат логов:</p>
20 <p>Также хорошей практикой считается логировать идентификатор, который поможет нам связать все логи в рамках одного запроса. Для этого нам нужно подключить к проекту пакет<em>github.com/gofiber/fiber/v2/middleware/requestid</em>. И инициализировать его перед посредником для логирования:</p>
20 <p>Также хорошей практикой считается логировать идентификатор, который поможет нам связать все логи в рамках одного запроса. Для этого нам нужно подключить к проекту пакет<em>github.com/gofiber/fiber/v2/middleware/requestid</em>. И инициализировать его перед посредником для логирования:</p>
21 <p>Запускаем веб-приложение и открываем в браузере страницу<em><a>http://localhost</a></em>. После этого проверяем консоль веб-приложения:</p>
21 <p>Запускаем веб-приложение и открываем в браузере страницу<em><a>http://localhost</a></em>. После этого проверяем консоль веб-приложения:</p>
22 <p>Мы видим, что теперь в каждом логе есть идентификатор запроса. Если что-то пойдет не так, по идентификатору мы сможем понять, в рамках какого запроса происходили ошибки. Это поможет при отладке или исправлении ошибок в работающем веб-приложении.</p>
22 <p>Мы видим, что теперь в каждом логе есть идентификатор запроса. Если что-то пойдет не так, по идентификатору мы сможем понять, в рамках какого запроса происходили ошибки. Это поможет при отладке или исправлении ошибок в работающем веб-приложении.</p>
23 <p>Логирование запросов помогает нам разобраться в возникающих ошибках, но есть посредники, которые позволяют предотвратить новые ошибки. Один из примеров таких посредников - ограничение количества запросов в единицу времени.</p>
23 <p>Логирование запросов помогает нам разобраться в возникающих ошибках, но есть посредники, которые позволяют предотвратить новые ошибки. Один из примеров таких посредников - ограничение количества запросов в единицу времени.</p>
24 <h2>Ограничение количества запросов</h2>
24 <h2>Ограничение количества запросов</h2>
25 <p>Представим, что у нас есть небольшое веб-приложение, у которого сто клиентов, и все работает бесперебойно. Конкурент завидует нашему успеху и решает написать скрипт, который будет отправлять миллионы запросов в наше приложение. Цель конкурента - вывести наши сервера из работы, чтобы клиенты не могли пользоваться приложением, и бизнес терял прибыль.</p>
25 <p>Представим, что у нас есть небольшое веб-приложение, у которого сто клиентов, и все работает бесперебойно. Конкурент завидует нашему успеху и решает написать скрипт, который будет отправлять миллионы запросов в наше приложение. Цель конкурента - вывести наши сервера из работы, чтобы клиенты не могли пользоваться приложением, и бизнес терял прибыль.</p>
26 <p>Чтобы защититься со стороны веб-приложения от таких атак, следует настроить ограничение количества запросов - throttling. Для этого мы будем использовать пакет<em>github.com/gofiber/fiber/v2/middleware/limiter</em>. Когда пакет подключен, мы можем настроить нового посредника, чтобы ограничить количество запросов с одного IP-адреса:</p>
26 <p>Чтобы защититься со стороны веб-приложения от таких атак, следует настроить ограничение количества запросов - throttling. Для этого мы будем использовать пакет<em>github.com/gofiber/fiber/v2/middleware/limiter</em>. Когда пакет подключен, мы можем настроить нового посредника, чтобы ограничить количество запросов с одного IP-адреса:</p>
27 <p>Запускаем веб-приложение и открываем в браузере страницу<em><a>http://localhost</a></em>четыре раза. На первые три запроса мы получаем ответ "OK", но на четвертый получаем ответ "Too Many Requests".</p>
27 <p>Запускаем веб-приложение и открываем в браузере страницу<em><a>http://localhost</a></em>четыре раза. На первые три запроса мы получаем ответ "OK", но на четвертый получаем ответ "Too Many Requests".</p>
28 <p>С помощью структуры limiter.Config мы установили максимальное количество запросов в единицу времени. В нашем случае это три запроса в десять секунд. Если мы превысим это количество, то наш запрос будет отклонен с кодом<em>429 (Too Many Requests)</em>, что мы и увидели на четвертый запрос. По истечении десяти секунд с момента первого запроса мы снова сможем открывать страницу и получать успешный ответ.</p>
28 <p>С помощью структуры limiter.Config мы установили максимальное количество запросов в единицу времени. В нашем случае это три запроса в десять секунд. Если мы превысим это количество, то наш запрос будет отклонен с кодом<em>429 (Too Many Requests)</em>, что мы и увидели на четвертый запрос. По истечении десяти секунд с момента первого запроса мы снова сможем открывать страницу и получать успешный ответ.</p>
29 <p>В данном примере мы использовали IP-адрес клиента, чтобы определить источник запроса. Но можно использовать любой другой идентификатор, например, идентификатор пользователя или сессии.</p>
29 <p>В данном примере мы использовали IP-адрес клиента, чтобы определить источник запроса. Но можно использовать любой другой идентификатор, например, идентификатор пользователя или сессии.</p>
30 <h2>Выводы</h2>
30 <h2>Выводы</h2>
31 <ul><li>Посредники позволяют выполнять действия до или после обработки запроса</li>
31 <ul><li>Посредники позволяют выполнять действия до или после обработки запроса</li>
32 <li>Fiber позволяет группировать обработчиков, чтобы один раз описывать всех посредников для группы обработчиков</li>
32 <li>Fiber позволяет группировать обработчиков, чтобы один раз описывать всех посредников для группы обработчиков</li>
33 <li>Посредники могут быть использованы для логирования запросов, проверки доступа, ограничения количества запросов</li>
33 <li>Посредники могут быть использованы для логирования запросов, проверки доступа, ограничения количества запросов</li>
34 </ul>
34 </ul>