Перейти к основному содержимому

Код вокруг каждого обработчика

Промежуточный слой (middleware) — это код, который выполняется вокруг ваших обработчиков: до того, как запрос доберётся до них, после того как ответ их покинет, или вместо них. Журналирование, аутентификация, ограничение частоты запросов, сжатие — всё это промежуточные слои.

Одна и та же идея встречается под тремя названиями: веб-фреймворки говорят middleware, gRPC говорит interceptor, в некоторых экосистемах говорят filter. Одно понятие, три словаря.

В PHP промежуточный слой — это функция, которая принимает обработчик — любой callable — и возвращает обёрнутый callable: это в точности паттерн Декоратор из группы паттернов проектирования, а стек таких слоёв ведёт себя как Цепочка обязанностей.


Промежуточный слой журналирования

withLog оборачивает любой обработчик: он записывает в журнал приходящий запрос, даёт обработчику сделать свою работу и записывает ещё раз на выходе. Сам обработчик остаётся совершенно не в курсе.

Сервер работает как отдельный процесс, поэтому его журнал сам по себе не попадает в терминал демонстрации — промежуточный слой дописывает строки в небольшой файл журнала, а демонстрация печатает свежие строки журнала после каждого запроса.

Обернуть один раз — журналировать всё

Обёрнутый обработчик обслуживает два разных пути, и оба попадают в журнал — журналирование написано один раз, в обёртке, а не в каждом обработчике.

Prompt
Напишите PHP-скрипт с промежуточным слоем withLog, который оборачивает handler-callable: перед вызовом следующего обработчика он записывает в журнал строку со стрелкой, методом и путём, а после — строку о завершении. Направьте два пути через обёрнутый обработчик, обслужите его встроенным сервером, запросите оба пути и напечатайте строки журнала и ответы.
Вывод: PHP-скрипт
Wrap once, log everything

Промежуточный слой, который останавливает запрос

Промежуточный слой может и отказать: проверка аутентификации, не нашедшая верного ключа, отвечает 401 Unauthorized и никогда не вызывает следующий обработчик.

Сцепленные как withLog(withAuth($handler)), они пропускают запрос через слои по порядку — и ответ всплывает обратно через них же.

Слой аутентификации в цепочке

Запрос без ключа останавливается слоем аутентификации с кодом 401 — обработчик так и не запускается. С ключом запрос проходит всю цепочку и добирается до данных.

Prompt
Напишите PHP-скрипт с двумя сцепленными промежуточными слоями: withLog, записывающий запрос в журнал, и withAuth, проверяющий заголовок X-API-Key и отвечающий 401 без вызова следующего обработчика, если ключ неверный. Оберните обработчик данных как withLog(withAuth($handler)), обслужите его встроенным сервером, затем отправьте один запрос без ключа и один с ключом, напечатав оба статуса и тела ответов.
Вывод: PHP-скрипт