API Index — Namespaces, Packages, Reports, Indices
HeaderMiddleware
in package
implements
MiddlewareInterface
Header Middleware
Declarative response-header manipulation. The most common use case is
stamping security headers (X-Frame-Options, CSP, Strict-Transport-Security,
X-Content-Type-Options, Referrer-Policy, Permissions-Policy) onto every
response without sprinkling $response->header(...) calls through handlers.
Apache equivalent (mod_headers):
Header set X-Frame-Options "DENY"
Header append Vary "Accept-Encoding"
Header unset Server
Header add Set-Cookie "..."
nginx equivalent:
add_header X-Frame-Options "DENY" always;
more_clear_headers Server; # ngx_headers_more module
Status-conditional application (nginx parity)
nginx add_header applies headers only on safe-status responses
(200, 201, 204, 206, 301, 302, 303, 304, 307, 308) unless the always
keyword is present. ZealPHP mirrors this behaviour through two knobs:
-
Constructor
$alwaysByDefault(defaulttrue): whentrueevery rule behaves like nginxadd_header ... always— headers are applied to ALL responses regardless of status. Set tofalseto switch the middleware into nginx-default mode whereset/add/appendrules are skipped on non-safe-status responses unless the per-rulealwaysflag overrides them.BC note: the default is
true(apply to all statuses) to preserve the behaviour of existing ZealPHP apps. nginx migrants who want exactadd_header-without-alwaysparity should passfalse. -
Per-rule
alwaysflag insideset/add/appendentries: wrap a value in['value' => '...', 'always' => true]to force a specific rule to apply on all statuses even when$alwaysByDefault = false.unsetrules are always unconditional — they run on every response status.
Safe statuses (matching nginx ngx_http_headers_filter_module.c:217-233):
200, 201, 204, 206, 301, 302, 303, 304, 307, 308.
Constructor accepts a config array with four operations:
set: overwrite the header value (replaces existing)add: append a value (like ApacheHeader add— emits multiple lines)append: append to existing value comma-separated (likeHeader append Vary "X")unset: list of headers to strip from the response (always unconditional)
Each rule value may be a plain string (or array for add) or an associative
array with 'value' and optional 'always' keys:
'set' => ['X-Frame-Options' => ['value' => 'DENY', 'always' => true]]
Usage in app.php — current default (all-status, BC-safe):
$app->addMiddleware(new \ZealPHP\Middleware\HeaderMiddleware([
'set' => [
'X-Frame-Options' => 'DENY',
'X-Content-Type-Options' => 'nosniff',
'Referrer-Policy' => 'strict-origin-when-cross-origin',
'Strict-Transport-Security' => 'max-age=31536000; includeSubDomains',
'Content-Security-Policy' => "default-src 'self'",
],
'append' => ['Vary' => 'Accept-Encoding'],
'unset' => ['Server', 'X-Powered-By'],
]));
Usage with nginx semantics (skip on error responses unless always=true):
$app->addMiddleware(new \ZealPHP\Middleware\HeaderMiddleware([
'set' => [
// Skipped on 4xx/5xx (nginx default behaviour).
'Cache-Control' => 'no-cache',
// Always applied even on error responses.
'X-Frame-Options' => ['value' => 'DENY', 'always' => true],
],
'unset' => ['Server'], // unset is always unconditional
], alwaysByDefault: false));
Table of Contents
Interfaces
- MiddlewareInterface
Constants
- SAFE_STATUSES : array<string|int, int> = [200, 201, 204, 206, 301, 302, 303, 304, 307, 308]
- nginx safe-status set: responses on which
add_headerfires withoutalways.
Properties
- $add : array<string, array<int, array{value: string, always: bool}>>
- Normalised
addrules: name => list<array{value: string, always: bool}>. - $append : array<string, array{value: string, always: bool}>
- Normalised
appendrules: name => ['value' => string, 'always' => bool]. - $set : array<string, array{value: string, always: bool}>
- Normalised
setrules: name => ['value' => string, 'always' => bool]. - $unset : array<string|int, string>
Methods
- __construct() : mixed
- process() : ResponseInterface
- normaliseAddRules() : array<string, array<int, array{value: string, always: bool}>>
- Normalise
addconfig entries into a uniform shape. - normaliseScalarRules() : array<string, array{value: string, always: bool}>
- Normalise
setandappendconfig entries into a uniform shape.
Constants
SAFE_STATUSES
nginx safe-status set: responses on which add_header fires without always.
private
array<string|int, int>
SAFE_STATUSES
= [200, 201, 204, 206, 301, 302, 303, 304, 307, 308]
Source: ngx_http_headers_filter_module.c:221-232.
Properties
$add
Normalised add rules: name => list<array{value: string, always: bool}>.
private
array<string, array<int, array{value: string, always: bool}>>
$add
$append
Normalised append rules: name => ['value' => string, 'always' => bool].
private
array<string, array{value: string, always: bool}>
$append
$set
Normalised set rules: name => ['value' => string, 'always' => bool].
private
array<string, array{value: string, always: bool}>
$set
$unset
private
array<string|int, string>
$unset
Methods
__construct()
public
__construct([array{set?: array, add?: array, append?: array, unset?: string[]} $config = [] ][, bool $alwaysByDefault = true ]) : mixed
Parameters
-
$config
: array{set?: array
, add?: array = [], append?: array , unset?: string[]} - $alwaysByDefault : bool = true
-
When true (the default), every rule applies to ALL responses regardless of HTTP status — this is ZealPHP's historical behaviour (equivalent to nginx
alwayson every rule). Set to false for nginx-default mode:set/add/appendrules are skipped on non-safe-status responses unless the per-rulealwaysflag is explicitly set.unsetrules are always unconditional in both modes.
process()
public
process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
Parameters
- $request : ServerRequestInterface
- $handler : RequestHandlerInterface
Return values
ResponseInterfacenormaliseAddRules()
Normalise add config entries into a uniform shape.
private
normaliseAddRules(array<string, string|array<string|int, string>|array{value: string|string[], always?: bool}> $rules, bool $alwaysByDefault) : array<string, array<int, array{value: string, always: bool}>>
Input allows: string, string[], or array{value: string|string[], always?: bool} Output: array<string, list<array{value: string, always: bool}>>
Parameters
- $rules : array<string, string|array<string|int, string>|array{value: string|string[], always?: bool}>
- $alwaysByDefault : bool
Return values
array<string, array<int, array{value: string, always: bool}>>normaliseScalarRules()
Normalise set and append config entries into a uniform shape.
private
normaliseScalarRules(array<string, string|array{value: string, always?: bool}> $rules, bool $alwaysByDefault) : array<string, array{value: string, always: bool}>
Input: array<string, string|array{value: string, always?: bool}> Output: array<string, array{value: string, always: bool}>
Parameters
- $rules : array<string, string|array{value: string, always?: bool}>
- $alwaysByDefault : bool