Перейти к содержимому
docs.
WORKSPACE

Документации проектов

Открыть каталог проектов
Localzet ServerАсинхронный PHP-серверTriangleФреймворк и компоненты✓MIX IDИдентификация и интеграцииHack APIПубличные API хакатонаACNПроект и компонентыUserlay / UserNetПроект и компонентыAxiomПроект и компонентыМесседжинг через почтуПроект и компонентыLWT / JWT / JOSEПроект и компонентыФинансовая аналитика KimaiПроект и компонентыМультипарадигмальная БДПроект и компонентыZorin PlatformПроект и компонентыZorin TrustПроект и компонентыFloraScope / VegwatchПроект и компонентыaegis-qДокументация проектаaevumdbДокументация проектаauditДокументация проектаauto-invest-managerАвтотрейдерcaine-companionДокументация проектаcertbot-cloudflareДокументация проектаClusterLocalzet Server / ClustercmdveilДокументация проектаConsolePHP CLICronБиблиотеки Localzet Serverdata-connectorДокументация проектаdevice-controlDevice Controlenn-projectДокументация проектаEventsБиблиотеки Localzet ServerflowsintДокументация проектаforgeДокументация проектаHttpClientБиблиотеки Localzet ServerinterpreterСобственный языкinvariaДокументация проектаkeynotesДокументация проектаknotrouteKnotroutelaravel-personal-analyticsДокументация проектаlocalzet-osДокументация проектаmeridianДокументация проектаMQTTБиблиотеки Localzet Servernano-kernelСобственная ОСNoterДокументация проектаpersonal-analyticsДокументация проектаProxyБиблиотеки Localzet ServerPSRБиблиотеки Localzet ServerPSR-7Библиотеки Localzet Serverrschs-monitorДокументация проектаsemsealДокументация проектаshardsealДокументация проектаSocketIOБиблиотеки Localzet ServerSOCKS5Библиотеки Localzet Serverstandalone-analyticsДокументация проектаstatic-php-cliДокументация проектаStorageБиблиотеки Localzet ServersutureДокументация проектаtempoweaveДокументация проектаttsСинтез речиTunnelБиблиотеки Localzet Serverui-kitUI KitvesperДокументация проектаWebAnalyzerWebAnalyzerzorin-access-brokerДокументация проектаzorin-authority-brokerДокументация проектаzorin-authority-sdk-phpДокументация проектаzorin-authority-sdk-pythonДокументация проектаzorin-authority-sdk-tsДокументация проектаzorin-client-intelДокументация проектаzorin-device-core-aospДокументация проектаzorin-host-agentДокументация проектаzorin-native-labДокументация проектаzorin-nodeДокументация проектаzorin-opsДокументация проектаdonstu-python-sdkДокументация проектаfloortraceFloortraceserver-rsLocalzet Server / Cluster
Каталог

Middleware

Triangle Middleware собирает цепочку обработчиков между HTTP-запросом и контроллером. Каждый обработчик может проверить запрос, завершить его собственным ответом либо вызвать следующий обработчик и изменить полученный ответ.

Это контракт Triangle, а не PSR-15: метод принимает request и callable следующего шага, а не ServerRequestInterface и RequestHandlerInterface.

Окно терминала
composer require triangle/middleware

Пакет объявляет PHP ^8.1, triangle/engine ^8.1 и triangle/router ^2.0. HTTP-цепочку исполняет Triangle Engine-HTTP; сам компонент хранит регистрации и собирает список callbacks.

<?php
namespace app\middleware;
use Triangle\Middleware\MiddlewareInterface;
final class ResponseHeader implements MiddlewareInterface
{
public function process($request, callable $handler)
{
$response = $handler($request);
return $response->header('X-Application', 'example');
}
}

До вызова handler удобно выполнять проверки, после — добавлять заголовки или метрики. Для отказа верните HTTP Response, не вызывая handler. Контроль доступа выполняйте на сервере; наличие middleware-класса в проекте не означает его включения в цепочку.

Не сохраняйте request, текущего пользователя или ответ в свойствах долгоживущего экземпляра middleware. Engine получает экземпляры из контейнера; время их жизни определяется контейнером и worker, а не названием метода process.

В middleware.php возвращается карта областей и списков классов:

return [
'@' => [app\middleware\ResponseHeader::class],
];

@ означает глобальный middleware. Пустая строка обозначает общий список текущего приложения/плагина; именованный ключ — отдельное приложение. Bootstrap дополнительно читает static.middleware для статических ресурсов в отдельную область static.

Load проверяет наличие метода process через method_exists, но не проверяет реализацию интерфейса, видимость и точную сигнатуру. Ошибка может проявиться уже при исполнении запроса; используйте MiddlewareInterface и проверяйте реальный HTTP-путь.

Маршрут может добавлять middleware через свой RouteObject. Контроллер может иметь свойство middleware со списком классов, а также атрибуты Triangle Annotation Middleware на классе и методе. Bootstrap собирает эти источники при подготовке callback; это не вызов каждого middleware при чтении конфигурации.

Для конфигурационных списков порядок объявления сохраняется при входе в HTTP-цепочку, а после handler обработчики завершаются в обратном порядке. Global идёт снаружи app-global, затем app и middleware контроллера/маршрута. Внутренний список getMiddleware намеренно развёрнут: Engine оборачивает им конечный callback. Не вызывайте этот список вручную как обычный foreach — это изменит контракт исполнения.

Маршрутный список дополнительно разворачивается при сборке, поэтому его порядок нужно сверять отдельно от конфигурационного. Атрибуты и controller property участвуют в той же композиции; при нескольких источниках закрепите ожидаемый trace интеграционным тестом.

Неправильный тип списка и отсутствующий process отклоняются при load. Повторный load дописывает registrations; он не заменяет предыдущую конфигурацию и может создать дубли. Start(null) ничего не загружает.

HTTP Engine перехватывает Throwable из process и переводит его через обработчик исключений приложения. Это не повтор операции: middleware с внешним побочным эффектом должен сам обеспечивать идемпотентность и понятную обработку отказа.

Triangle\Middleware\MiddlewareInterface::process($request, callable $handler) не задаёт return type. HTTP-приложение ожидает результат, совместимый с его Response-цепочкой. Вызов handler обязателен только когда запрос должен пройти дальше.

У интерфейса два аргумента. Не переносите сюда пример Engine-WS с иным транспортным контрактом: совпадающее слово middleware не делает сигнатуры взаимозаменяемыми.

МетодНазначение
start(?localzet\Server $server = null): voidЗагрузить middleware приложения, static и плагинов; при null ничего не делать
load(array $list, string $plugin = ''): voidДобавить registrations по областям
getMiddleware(string $plugin, string $app, string|array|Closure $controller, ?RouteObject $route, bool $withGlobal = true): arrayСобрать callbacks для оборачивания конечного handler

Load сохраняет пары [class, 'process'], не создавая экземпляры. HTTP Engine затем разрешает class через container->get. Опция withGlobal=false исключает global и app-global, но не список конкретного app и не middleware route/controller.

КлючОбласть
@Глобальная, без plugin
пустая строкаОбщая для текущего plugin/application namespace
имя приложенияКонкретное приложение
staticСтатические ресурсы
plugin.{plugin}.{app}Явно указанный plugin/app при стандартном app.plugin_alias

При встрече @ loader сбрасывает локальную переменную plugin, которая затем используется для следующих ключей того же load. Поэтому не смешивайте @ и неявные plugin-scoped entries в одном списке: последующие записи могут попасть в иной scope. Используйте отдельные вызовы/явные plugin-ключи и проверяйте результат сборки.

GetMiddleware возвращает array_reverse от объединения global, app-global, app и локальных controller/route списков. Engine-HTTP выполняет array_reduce и создаёт вложенные closures, поэтому первый объявленный global оказывается внешним обработчиком. Возврат после handler идёт в обратном порядке.

Маршрутный RouteObject::getMiddleware предварительно разворачивается отдельно. Контроллер определяется как массив с именем класса в первом элементе; готовый объект в таком массиве не проходит эту ветку reflection.

Install копирует отсутствующий middleware.php. Поставляемая конфигурация содержит пустой список для ключа ”. Существующая конфигурация не заменяется автоматически, а регистрация класса в Composer autoload сама по себе middleware не включает.