Skip to content

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 neexistuje
  • handle() - Zavolá handle na všechny middlewares zadané v pipeline
  • process() - 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();

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