Middlewares PSR-15
Middlewary řídí výkonný tok požadavků přes aplikaci. Volají se v routách pro kontrolu dat, přihlášení, atp.
Využíváme Silera a Laminas řešení: - Laminas Diactoros - Laminas Stratigility
Koncept
Middleware má argumenty $request (PSR-7) a $handler (PSR-15) a musí vrátit ResponseInterface.
Parametry mezi jednotlivými middlewares lze předávat pomocí $request->withAttribute() a získání pomocí $request->getAttribute().
Vzor je jasný, lze se inspirovat v Laminas či Slim a použít či okoukat již hotové middlewares z awesome-psr15-middlewares.
Typické případy
- User authorization (ověření uživatele)
- Logging (logování)
- Handling exceptions (ošetření chyb)
- Rate-limiting (omezení počtu požadavků)
- Handling CORS
- Encrypted Cookies
- CSRF protection
Pro kontrolu HTTP dat využíváme Rakit validation.
Princip fungování
Middlewares se odkazují v pipeline postupně jeden na druhý. Poslední middleware musí být jiný - musí mít doplněn handler, který odešle finální odpověď.
Request → Middleware 1 → Middleware 2 → ... → Controller (handler)
Response ← Middleware 1 ← Middleware 2 ← ... ← Handler response
Siler Middlewares
Siler využívá Laminas řešení Diactoros a Stratigility a doplňuje je funkcionálním řešením s callable middlewares jako funkce.
Middleware je dle PSR-15:
- Funkce s parametry $request (ServerRequestInterface) a $handler (RequestHandlerInterface)
- Vždy vrací odpověď (ResponseInterface)
Funkce Siler\Stratigility
use function Siler\Stratigility\pipe;
use function Siler\Stratigility\handle;
use function Siler\Stratigility\process;
pipe()- Přidá MiddlewareInterface do pipeline, vytvoří ji pokud neexistujehandle()- Zavolá handle na všechny middlewares zadané v pipelineprocess()- Process pipeline zabalená na Siler routu (speciální věc Sileru)
Příklady
Jednoduchý middleware
$userMiddleware = function ($request, $handler) {
$request = $request->withAttribute('user', 'petrovo');
return $handler->handle($request);
};
V route
use Siler\Diactoros;
use Siler\Route;
use function Siler\Stratigility\pipe;
use function Siler\Stratigility\process;
pipe(settingMiddleware, 'frontend');
pipe(sanitizationMiddleware, 'frontend');
$request = Diactoros\request();
$handler = fn($request, $params) => require_fn(DIR . '/app/Controllers/home.php')($params);
Route\get('/', process($request, 'frontend')($handler), $request);
Bez route (základní pipeline)
use Siler\Diactoros;
use Siler\HttpHandlerRunner;
use function Siler\Stratigility\handle;
use function Siler\Stratigility\pipe;
$userMiddleware = function ($request, $handler) {
$request->getAttribute('user', 'petrovo');
return $handler->handle($request);
};
$user2Middleware = function ($request, $handler) {
$request->getAttribute('user2', 'user2');
return $handler->handle($request);
};
$finalMiddleware = function ($request) {
$controller = require_fn(DIR . '/app/Controllers/home.php');
$controller();
};
$request = Diactoros\request();
pipe($userMiddleware);
pipe($user2Middleware);
pipe($finalMiddleware);
$response = handle($request);
HttpHandlerRunner\sapi_emit($response);
exit();
Navržené middlewares
Každý middleware je v jednom souboru v adresáři dle skupin a musí se zapsat do composer.json do sekce "files":
"app/Middlewares/App/settingMiddleware.php",
"app/Middlewares/Auth/loginAdminMiddleware.php",
"app/Middlewares/Auth/loginMiddleware.php",
"app/Middlewares/Auth/logoutAdminMiddleware.php",
"app/Middlewares/Auth/logoutMiddleware.php",
"app/Middlewares/Input/adminAjaxDataMiddleware.php",
"app/Middlewares/Input/adminCubeDataMiddleware.php",
"app/Middlewares/Input/csrfMiddleware.php",
"app/Middlewares/Input/sanitizationMiddleware.php",
"app/Middlewares/Log/loggingAdminMiddleware.php",
"app/Middlewares/Request/proxyMiddleware.php",
"app/Middlewares/Request/staticBlockerMiddleware.php",
"app/Middlewares/Response/headersMiddleware.php",
"app/Middlewares/Restriction/corsMiddleware.php",
"app/Middlewares/Restriction/ipFilteringMiddleware.php",
"app/Middlewares/Session/sessionExpirationAdminMiddleware.php",
"app/Middlewares/Url/defineWebMiddleware.php",
"app/Middlewares/Url/redirectionMiddleware.php",
"app/Middlewares/finalHandler.php",
Skupiny middlewares
App
- settingMiddleware - Načítá aplikační nastavení
Auth
- loginAdminMiddleware - Ověří přihlášení admin uživatele
- loginMiddleware - Ověří přihlášení uživatele na frontendu
- logoutAdminMiddleware - Zpracuje admin odhlášení
- logoutMiddleware - Zpracuje odhlášení
Input
- adminAjaxDataMiddleware - Zpracovává AJAX data v adminu
- adminCubeDataMiddleware - Zpracovává data kostek v adminu
- csrfMiddleware - CSRF ochrana
- sanitizationMiddleware - Čistí vstupní data
Log
- loggingAdminMiddleware - Loguje akce v adminu
Request
- proxyMiddleware - při proxy nastavuje globální $_SERVER proměnné
- staticBlockerMiddleware - neexistující statické soubory neprojdou do php
Response
- headersMiddleware - Nastavuje response headery
Restriction
- corsMiddleware - CORS pravidla
- ipFilteringMiddleware - IP filtrování
Request
- sessionExpirationAdminMiddleware - kontroluje expiraci sessionu v adminu
URL
- defineWebMiddleware - Definuje web kontext (URL, jazyk, atd.)
- redirectionMiddleware - řeší přesměrovávání
Final
- finalHandler - Finální handler pro výstup