Middlewares PSR-15¶
Middleware řídí tok požadavku skrz aplikaci: auth, CSRF, session, CORS, logování, hlavičky a další cross-cutting logiku.
Petrovo CMS používá vlastní PSR-15 pipeline Core\Middleware.
Koncept¶
Middleware v Petrovo:
// app/Middlewares/Session/authGuardMiddleware.php
namespace App\Middlewares;
use Psr\Http\Message\ResponseInterface;
function authGuardMiddleware($request, $handler): ResponseInterface
{
// 1. Logika PŘED handlerem
$userId = getSessionUserId();
if (!$userId && isProtectedPath($request)) {
return redirectToLogin();
}
// 2. Předej request dál
$request = $request->withAttribute('user_id', $userId);
$response = $handler->handle($request);
// 3. Logika PO handleru (úprava response)
$response = $response->withHeader('X-Runtime', (string) microtime(true));
return $response;
}
// V route souboru — zaregistruj do pipeline (first-class callable):
use function Core\Middleware\pipe;
use function App\Middlewares\authGuardMiddleware;
pipe(authGuardMiddleware(...), 'admin');
// Middleware se aplikuje automaticky na routy s 'admin' pipeline
Klíčové body:
- Middleware dostává
ServerRequestInterfaceaRequestHandlerInterface - Voláš
$handler->handle($request)aby pokračoval do dalšího middleware - Parametry mezi middleware:
$request->withAttribute()a$request->getAttribute() - Middleware se spouští v pořadí registrace
Funkce Core\Middleware¶
pipe($middleware, 'name')- Zaregistruj middleware do pipelineprocess('name')- Vrací closure pro wrappování middleware okolo handleruhandle($request, 'name')- Spustí middleware pipeline bez handlerureset()- Vyčisti všechny pipeline (testování)get_pipelines()- Debug - vrací registrované pipeline
Praktické Příklady¶
Jednoduchý logging middleware¶
// app/Middlewares/Request/loggingMiddleware.php
namespace App\Middlewares;
use Psr\Http\Message\ResponseInterface;
function loggingMiddleware($request, $handler): ResponseInterface
{
$method = $request->getMethod();
$path = $request->getUri()->getPath();
error_log("→ $method $path");
$response = $handler->handle($request);
error_log("← " . $response->getStatusCode());
return $response;
}
// V route souboru:
use function Core\Middleware\pipe;
use function App\Middlewares\loggingMiddleware;
pipe(loggingMiddleware(...), 'admin');
Middleware s autentifikací¶
// app/Middlewares/Auth/authMiddleware.php
namespace App\Middlewares;
use Psr\Http\Message\ResponseInterface;
use function Core\Http\text;
function authMiddleware($request, $handler): ResponseInterface
{
$token = $request->getHeaderLine('Authorization');
if (!$token || !validateToken($token)) {
return text('Unauthorized', 401);
}
// Úspěšně autentifikován - pokračuj
return $handler->handle($request);
}
// pipe(authMiddleware(...), 'api');
Middleware který mění request¶
// app/Middlewares/Request/userMiddleware.php
namespace App\Middlewares;
use Psr\Http\Message\ResponseInterface;
function userMiddleware($request, $handler): ResponseInterface
{
$userId = Session::get('user_id');
if ($userId) {
// Načti user z DB a přidej do request
$user = DB::row("SELECT * FROM users WHERE id = ?", [$userId]);
$request = $request->withAttribute('user', $user);
}
return $handler->handle($request);
}
// pipe(userMiddleware(...), 'admin');
Middleware který mění response¶
// app/Middlewares/Response/securityHeadersMiddleware.php
namespace App\Middlewares;
use Psr\Http\Message\ResponseInterface;
function securityHeadersMiddleware($request, $handler): ResponseInterface
{
$response = $handler->handle($request);
// Přidej security headers
return $response
->withHeader('X-Content-Type-Options', 'nosniff')
->withHeader('X-Frame-Options', 'SAMEORIGIN')
->withHeader('X-XSS-Protection', '1; mode=block')
->withHeader('Strict-Transport-Security', 'max-age=31536000');
}
// pipe(securityHeadersMiddleware(...), 'website');
Implementované middlewares¶
Middleware soubory se autoloadují přes composer.json sekci "files":
{
"autoload": {
"files": [
"app/Middlewares/Auth/authAdminMiddleware.php",
"app/Middlewares/Auth/permissionAdminMiddleware.php",
"app/Middlewares/Auth/authMiddleware.php",
"app/Middlewares/Input/csrfAdminMiddleware.php",
"app/Middlewares/Input/csrfMiddleware.php",
"app/Middlewares/Log/loggingAdminMiddleware.php",
"app/Middlewares/Request/proxyMiddleware.php",
"app/Middlewares/Response/headersMiddleware.php",
"app/Middlewares/Restriction/corsMiddleware.php",
"app/Middlewares/Restriction/ipBlacklistMiddleware.php",
"app/Middlewares/Restriction/ipFilteringMiddleware.php",
"app/Middlewares/Session/sessionExpirationAdminMiddleware.php",
"app/Middlewares/Url/redirectionMiddleware.php"
]
}
}
Struktura middleware souboru:
<?php
declare(strict_types=1);
namespace App\Middlewares;
use Psr\Http\Message\ResponseInterface;
function customMiddleware($request, $handler): ResponseInterface
{
// ... logika ...
return $handler->handle($request);
}
Aktuální skupiny middleware¶
Auth¶
authAdminMiddlewarekontroluje admin session a passkey login flowpermissionAdminMiddlewarehlídá admin oprávněníauthMiddlewareřeší autentizaci na frontendu
Input¶
csrfAdminMiddlewareověřuje CSRF v adminucsrfMiddlewareověřuje CSRF na website a/RUN
Log¶
loggingAdminMiddlewareloguje admin akce
Request¶
proxyMiddlewareupravuje request/server kontext za proxy
Response¶
headersMiddlewarenastavuje response hlavičky
Restriction¶
corsMiddlewareřeší CORSipBlacklistMiddlewareblokuje blacklistované IPipFilteringMiddlewareřeší IP omezení v jiných částech systému
Session¶
sessionExpirationAdminMiddlewareřeší timeout a obnovu admin session
Url¶
redirectionMiddlewareřeší redirect logiku starých URL