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

ResponseMiddleware
in package
implements MiddlewareInterface

The router / dispatch middleware (innermost PSR-15 layer).

Extracted verbatim from src/App.php (Phase 0 structural relocation). FQCN unchanged (ZealPHP\ResponseMiddleware) — it is both the injected $app handler param and the dispatch terminal of the middleware onion.

Table of Contents

Interfaces

MiddlewareInterface

Methods

buildTraceEcho()  : string
Reconstruct the request line + headers for a TRACE echo body, mirroring Apache's ap_send_http_trace() (http_filters.c:1130). Format is the request line, each header as Name: value, then a terminating blank line — the message/http representation the client sent. Header names/values are passed through verbatim (TRACE is an introspection echo); CR/LF inside a value is stripped so a crafted header can't inject extra wire lines.
dispatchMatched()  : ResponseInterface
Invoke the matched route handler with reflection-injected params and apply the universal return contract. This is the dispatch terminal — the path a route takes once any per-route middleware have run (or immediately, for a route with none).
dispatchRoute()  : ResponseInterface
Dispatch gate. When the matched route carries per-route middleware (resolved to instances once at App::run()), run the request through that PSR-15 chain — each middleware wrapping the next, the innermost terminal invoking the route handler via dispatchMatched(). Fast path: routes with no middleware (the overwhelming majority) go straight to dispatchMatched with zero added work, byte-for-byte the pre-feature behaviour. Fallback / error-handler dispatches carry no 'middleware' key, so they fast-path too.
matchAndDispatch()  : ResponseInterface
Match the (normalized) request URI against the route table and dispatch: exact-path match, then pattern match, else 405 / fallback / 404. Reads the normalized URI from $g->server['REQUEST_URI']. Extracted from process() so App::when() path-scoped middleware can wrap it — it is also the terminal of that onion (PathDispatchHandler).
process()  : ResponseInterface
dispatchRawRoute()  : ResponseInterface
dispatchRouteInner()  : ResponseInterface
The middleware-vs-direct dispatch decision, factored out so dispatchRoute() can wrap it with the per-route backend override.
dispatchWithMiddleware()  : ResponseInterface
Run the matched route's middleware onion, then the handler. The onion is assembled fresh per request from a few lightweight RequestHandler wrappers — the EXPENSIVE work (alias resolution + instantiation) was done once at boot — with the matched params baked into the terminal, so the chain holds no shared per-request state and is re-entrant-safe. The first-listed middleware ends up outermost (runs first), consistent with the global stack. A middleware that returns without calling the handler (a 403/redirect) short-circuits before the route handler runs.
statusOnlyResponse()  : ResponseInterface
Map a status-only int return (the universal return contract's return <int>; shape) to a PSR-7 response. Coerces out-of-range codes to 500 (Apache parity) and — crucially — routes any 4xx/5xx through renderError() so a registered custom error page fires. Shared by the raw and non-raw dispatch paths so both honour the contract identically (#259: raw routes previously emitted a bare empty-body status, skipping the error page).

Methods

buildTraceEcho()

Reconstruct the request line + headers for a TRACE echo body, mirroring Apache's ap_send_http_trace() (http_filters.c:1130). Format is the request line, each header as Name: value, then a terminating blank line — the message/http representation the client sent. Header names/values are passed through verbatim (TRACE is an introspection echo); CR/LF inside a value is stripped so a crafted header can't inject extra wire lines.

public static buildTraceEcho(string $method, string $uri, string $protocol, array<string, string> $headers) : string
Parameters
$method : string
$uri : string
$protocol : string
$headers : array<string, string>
Return values
string

dispatchMatched()

Invoke the matched route handler with reflection-injected params and apply the universal return contract. This is the dispatch terminal — the path a route takes once any per-route middleware have run (or immediately, for a route with none).

public dispatchMatched(array<string, mixed> $route, array<string, mixed> $params, string $method) : ResponseInterface
Parameters
$route : array<string, mixed>
$params : array<string, mixed>
$method : string
Return values
ResponseInterface

dispatchRoute()

Dispatch gate. When the matched route carries per-route middleware (resolved to instances once at App::run()), run the request through that PSR-15 chain — each middleware wrapping the next, the innermost terminal invoking the route handler via dispatchMatched(). Fast path: routes with no middleware (the overwhelming majority) go straight to dispatchMatched with zero added work, byte-for-byte the pre-feature behaviour. Fallback / error-handler dispatches carry no 'middleware' key, so they fast-path too.

public dispatchRoute(array<string, mixed> $route, array<string, mixed> $params, string $method[, ServerRequestInterface|null $request = null ]) : ResponseInterface
Parameters
$route : array<string, mixed>
$params : array<string, mixed>
$method : string
$request : ServerRequestInterface|null = null
Return values
ResponseInterface

matchAndDispatch()

Match the (normalized) request URI against the route table and dispatch: exact-path match, then pattern match, else 405 / fallback / 404. Reads the normalized URI from $g->server['REQUEST_URI']. Extracted from process() so App::when() path-scoped middleware can wrap it — it is also the terminal of that onion (PathDispatchHandler).

public matchAndDispatch(ServerRequestInterface $request, string $method) : ResponseInterface
Parameters
$request : ServerRequestInterface
$method : string
Return values
ResponseInterface

process()

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

dispatchRawRoute()

private dispatchRawRoute(array<string, mixed> $route, array<string, mixed> $params, string $method) : ResponseInterface
Parameters
$route : array<string, mixed>
$params : array<string, mixed>
$method : string
Return values
ResponseInterface

dispatchRouteInner()

The middleware-vs-direct dispatch decision, factored out so dispatchRoute() can wrap it with the per-route backend override.

private dispatchRouteInner(array<string, mixed> $route, array<string, mixed> $params, string $method, ServerRequestInterface|null $request) : ResponseInterface
Parameters
$route : array<string, mixed>
$params : array<string, mixed>
$method : string
$request : ServerRequestInterface|null
Return values
ResponseInterface

dispatchWithMiddleware()

Run the matched route's middleware onion, then the handler. The onion is assembled fresh per request from a few lightweight RequestHandler wrappers — the EXPENSIVE work (alias resolution + instantiation) was done once at boot — with the matched params baked into the terminal, so the chain holds no shared per-request state and is re-entrant-safe. The first-listed middleware ends up outermost (runs first), consistent with the global stack. A middleware that returns without calling the handler (a 403/redirect) short-circuits before the route handler runs.

private dispatchWithMiddleware(array<string, mixed> $route, array<string, mixed> $params, string $method, array<int|string, mixed> $chain, ServerRequestInterface|null $request) : ResponseInterface
Parameters
$route : array<string, mixed>
$params : array<string, mixed>
$method : string
$chain : array<int|string, mixed>
$request : ServerRequestInterface|null
Return values
ResponseInterface

statusOnlyResponse()

Map a status-only int return (the universal return contract's return <int>; shape) to a PSR-7 response. Coerces out-of-range codes to 500 (Apache parity) and — crucially — routes any 4xx/5xx through renderError() so a registered custom error page fires. Shared by the raw and non-raw dispatch paths so both honour the contract identically (#259: raw routes previously emitted a bare empty-body status, skipping the error page).

private statusOnlyResponse(int $rawStatus) : ResponseInterface
Parameters
$rawStatus : int
Return values
ResponseInterface
On this page