API Index — Namespaces, Packages, Reports, Indices
ETagMiddleware
in package
implements
MiddlewareInterface
ETag / Conditional-Request Middleware
Generates a weak ETag from a hash of the response body and evaluates the
RFC 9110 conditional-request preconditions in Apache's ap_meets_conditions
order via ConditionalRequest: If-Match -> If-Unmodified-Since ->
If-None-Match -> If-Modified-Since.
Outcomes:
304 Not Modified—GET/HEADwhose validators say "unchanged".412 Precondition Failed— failedIf-Match/If-Unmodified-Since, or a matchedIf-None-Matchon a non-GET/HEADmethod.- otherwise the original response, with an
ETagheader onGET/HEAD.
Usage in app.php:
$app->addMiddleware(new \ZealPHP\Middleware\ETagMiddleware());
Streaming responses (SSE, stream(), Generator yield) are skipped — they have
no buffered body to hash.
ETag derivation across paths (audit gap H7): ZealPHP emits weak ETags
everywhere, but the validator's input depends on how the response is
produced — exactly as Apache differs between static and dynamic content:
- Buffered / dynamic responses (this middleware):
W/"xxh3(body)". - Zero-copy file sends (Response::sendFile()):
W/"mtime-size"(stat-based, no body hash — Apache never hashes a static file body either). The two paths are mutually exclusive per response: this middleware bails on streaming responses and on an empty buffered body (sendFile()streams), so it never overwrites a stat-basedETag. Because both forms are weak, a URL that switches serving path produces a cache miss (full200), never a corrupt304— weak comparison can't false-match across the two namespaces.
Table of Contents
Interfaces
- MiddlewareInterface
Methods
- process() : ResponseInterface
- conditionalHeaders() : array<string, string>
- Collect the conditional-request headers the evaluator consults into a plain map. PSR-7 stores comma-joined values, which is exactly the list form {@see ConditionalRequest} parses.
Methods
process()
public
process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
Parameters
- $request : ServerRequestInterface
- $handler : RequestHandlerInterface
Return values
ResponseInterfaceconditionalHeaders()
Collect the conditional-request headers the evaluator consults into a plain map. PSR-7 stores comma-joined values, which is exactly the list form {@see ConditionalRequest} parses.
private
conditionalHeaders(ServerRequestInterface $request) : array<string, string>
Parameters
- $request : ServerRequestInterface