Alpha ZealPHP is early-stage and under active development. APIs may change between minor versions until v1.0. Feedback and bug reports welcome on GitHub.
API Index — Namespaces, Packages, Reports, Indices

CompressionMiddleware
in package
implements MiddlewareInterface

Compression Middleware (gzip / deflate)

Compresses response bodies when the client advertises support via Accept-Encoding. Skips streaming responses (SSE, Generator, stream()), responses smaller than the threshold, and optionally requests that already came through a reverse proxy such as Traefik.

RFC 7231 §5.3.4 compliance:

  • Accept-Encoding q=0 is treated as explicit refusal; compression is skipped.

RFC 7232 §2.1 compliance:

  • Strong ETags on responses that are then compressed are weakened (W/ prefix), because the compressed body is not byte-identical to the original.

nginx / mod_deflate parity:

  • Vary: Accept-Encoding is merged with any existing Vary values so that a prior Vary: Origin from CorsMiddleware is preserved (apr_table_mergen / ngx_http_header_filter parity).
  • Accept-Ranges is cleared on compressed responses because Range requests cannot be satisfied on a compressed body (ngx_http_clear_accept_ranges parity).

Reference usage when OpenSwoole http_compression is disabled: $app->addMiddleware(new \ZealPHP\Middleware\CompressionMiddleware());

Table of Contents

Interfaces

MiddlewareInterface

Constants

PROXY_HEADERS  : mixed = ['Forwarded', 'Via', 'X-Forwarded-For', 'X-Forw...

Properties

$level  : int
$minLength  : int
$skipProxiedRequests  : bool

Methods

__construct()  : mixed
process()  : ResponseInterface
applyCompressionHeaders()  : ResponseInterface
Apply the standard post-compression response headers: - Content-Encoding - Content-Length (actual compressed byte count) - Vary: merge Accept-Encoding into any existing values (dedup, case-insensitive) - ETag: weaken any strong ETag (RFC 7232 §2.1) - Accept-Ranges: clear (compressed body cannot serve byte-range requests)
isAcceptedEncoding()  : bool
Check whether a given encoding token is accepted by the client, honouring RFC 7231 §5.3.4 q-value semantics: q=0 (or q=0.000…) means explicit refusal.
isProxiedRequest()  : bool
isUncompressible()  : bool
mergeVary()  : ResponseInterface
Merge $directive into the response's Vary header, deduplicating case-insensitively. Uses withHeader() on the merged result so the full canonical list is a single header line (RFC 7230 §3.2.2).
weakenEtag()  : ResponseInterface
If the response carries a strong ETag, weaken it by prepending W/.

Constants

PROXY_HEADERS

private mixed PROXY_HEADERS = ['Forwarded', 'Via', 'X-Forwarded-For', 'X-Forwarded-Host', 'X-Forwarded-Port', 'X-Forwarded-Proto', 'X-Forwarded-Prefix', 'X-Forwarded-Server', 'X-Real-IP']

Properties

Methods

__construct()

public __construct([int $minLength = 1024 ][, int $level = 6 ][, bool $skipProxiedRequests = false ]) : mixed
Parameters
$minLength : int = 1024
$level : int = 6
$skipProxiedRequests : bool = false

process()

public process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
Parameters
$request : ServerRequestInterface
$handler : RequestHandlerInterface
Return values
ResponseInterface

applyCompressionHeaders()

Apply the standard post-compression response headers: - Content-Encoding - Content-Length (actual compressed byte count) - Vary: merge Accept-Encoding into any existing values (dedup, case-insensitive) - ETag: weaken any strong ETag (RFC 7232 §2.1) - Accept-Ranges: clear (compressed body cannot serve byte-range requests)

private applyCompressionHeaders(ResponseInterface $response, string $encoding, string $compressed) : ResponseInterface
Parameters
$response : ResponseInterface
$encoding : string
$compressed : string
Return values
ResponseInterface

isAcceptedEncoding()

Check whether a given encoding token is accepted by the client, honouring RFC 7231 §5.3.4 q-value semantics: q=0 (or q=0.000…) means explicit refusal.

private isAcceptedEncoding(string $accept, string $encoding) : bool

Parses the comma-separated Accept-Encoding field value looking for the token (case-insensitive, already lowercased by the caller). If the token is found and its q-value is absent or > 0, it is accepted. A q-value of exactly zero (any number of trailing zeros, e.g. "0", "0.0", "0.000") means the encoding is explicitly refused.

Parameters
$accept : string
$encoding : string
Return values
bool

isProxiedRequest()

private isProxiedRequest(ServerRequestInterface $request) : bool
Parameters
$request : ServerRequestInterface
Return values
bool

isUncompressible()

private isUncompressible(string $ct) : bool
Parameters
$ct : string
Return values
bool

mergeVary()

Merge $directive into the response's Vary header, deduplicating case-insensitively. Uses withHeader() on the merged result so the full canonical list is a single header line (RFC 7230 §3.2.2).

private mergeVary(ResponseInterface $response, string $directive) : ResponseInterface

Apache parity: apr_table_mergen(r->headers_out, "Vary", "Accept-Encoding") nginx parity: ngx_http_header_filter Vary conditional add

Parameters
$response : ResponseInterface
$directive : string
Return values
ResponseInterface

weakenEtag()

If the response carries a strong ETag, weaken it by prepending W/.

private weakenEtag(ResponseInterface $response) : ResponseInterface

A compressed body is a transformed representation — it is NOT byte-identical to the original, so the strong validator must not survive.

nginx parity: ngx_http_weak_etag() (ngx_http_core_module.c:1753) RFC reference: RFC 7232 §2.1

Parameters
$response : ResponseInterface
Return values
ResponseInterface
On this page