Middleware
ZealPHP uses PSR-15 middleware. Add with $app->addMiddleware(). The last added runs outermost (first to process request, last to process response).
Built-in middleware
| Class | Constructor | What it does |
|---|---|---|
CorsMiddleware | ($origins, $methods, $headers, $credentials, $maxAge) | CORS preflight + Access-Control headers on every response |
ETagMiddleware | (none) | Generates W/"md5" ETag, returns 304 on cache hit |
CompressionMiddleware | ($minLength=1024, $level=6, $skipProxiedRequests=false) | Reference gzip/deflate middleware; runtime compression is handled by OpenSwoole by default |
app.php — middleware registration order
$app->addMiddleware(new CorsMiddleware()); // outermost — handles preflight
$app->addMiddleware(new ETagMiddleware()); // generates ETag
$app->addMiddleware(new AuthMiddleware()); // your custom middleware
// ResponseMiddleware is always innermost (built-in)
Live demos
GET
CORS — Access-Control-Allow-Origin on every response
// Add middleware once in app.php:
$app->addMiddleware(new CorsMiddleware(['*']));
// Hit any endpoint with Origin header:
// curl -H "Origin: http://app.test" https://php.zeal.ninja/demo/middleware/cors
// → Access-Control-Allow-Origin: *
LIVE OUTPUT
Click Run →
GET
ETag / 304 — conditional GET
// ETagMiddleware auto-generates W/"md5(body)" on GET
// Second request with If-None-Match: <etag> → 304 Not Modified
// First hit:
// curl -D - https://php.zeal.ninja/http/etag-test
// → ETag: W/"abc..."
// Second hit:
// curl -H 'If-None-Match: W/"abc..."' https://php.zeal.ninja/http/etag-test
// → HTTP/1.1 304 Not Modified (empty body)
LIVE OUTPUT
Click Run →
GET
Compression — gzip when Accept-Encoding: gzip
// OpenSwoole handles runtime compression by default.
// Keep CompressionMiddleware only as a reference if you disable http_compression.
// curl --compressed https://php.zeal.ninja/http/compress-test
// → Content-Encoding: gzip (body is compressed)
LIVE OUTPUT
Click Run →
Custom middleware
use Psr\Http\Message\{ResponseInterface, ServerRequestInterface};
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
class TimingMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$start = microtime(true);
$response = $handler->handle($request); // call inner stack
$elapsed = round((microtime(true) - $start) * 1000, 2);
response_add_header('X-Response-Time', "$elapsed ms");
return $response;
}
}
// Register:
$app->addMiddleware(new TimingMiddleware());