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

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

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

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

В TypeScript middleware — это функция, которая принимает обработчик и возвращает обёрнутый обработчик, то есть в точности паттерн Decorator из группы паттернов проектирования, а стопка таких функций ведёт себя как Chain of Responsibility.


Middleware для логирования

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

Настоящее логирование обычно добавляет метку времени и длительность. В этих примерах и то и другое намеренно опущено, чтобы печатаемый вывод был одинаковым при каждом запуске.

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

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

Prompt
Напишите программу на TypeScript с middleware withLogging, которое принимает обработчик и возвращает обёрнутый обработчик, печатая строку со стрелкой, методом и путём перед вызовом следующего обработчика и строку о завершении после него. Оберните небольшой роутер с двумя маршрутами, запустите его на порту 0, запросите оба пути с помощью fetch и напечатайте ответы.
Вывод: программа на TypeScript и захваченный вывод
Wrap once, log everything

Middleware, которое останавливает запрос

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

Собранный в цепочку как withLogging(withAuth(handler)), запрос проходит через слои по порядку, а ответ возвращается обратно через них.

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

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

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