Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ public function __construct(...$middleware)
if ($needsAccessLog instanceof Container) {
\array_unshift($handlers, $needsAccessLog->getAccessLogHandler());
}

$this->router = new RouteHandler($container);
$errorHandler = \array_reduce($handlers, function ($carry, $handler) {
return $carry ?? ($handler instanceof ErrorHandler ? $handler : null);
});
$this->router = new RouteHandler($container, $errorHandler);
$handlers[] = $this->router;
$this->handler = new MiddlewareHandler($handlers);
$this->sapi = \PHP_SAPI === 'cli' ? new ReactiveHandler($container->getEnv('X_LISTEN')) : new SapiHandler();
Expand Down
4 changes: 2 additions & 2 deletions src/Io/RouteHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ class RouteHandler
/** @var Container */
private $container;

public function __construct(Container $container = null)
public function __construct(Container $container = null, ErrorHandler $errorHandler = null)
{
$this->routeCollector = new RouteCollector(new RouteParser(), new RouteGenerator());
$this->errorHandler = new ErrorHandler();
$this->errorHandler = $errorHandler ?? new ErrorHandler();
$this->container = $container ?? new Container();
}

Expand Down
26 changes: 26 additions & 0 deletions tests/AppTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,32 @@ public function testInvokeWithMatchingRouteReturnsInternalServerErrorResponseWhe
$this->assertStringContainsString("<p>Expected request handler to return <code>Psr\Http\Message\ResponseInterface</code> but got <code>null</code>.</p>\n", (string) $response->getBody());
}

public function testRouteHandlerUsesErrorHandlerPassedFromApp(): void
{
$errorHandler = $this->createMock(ErrorHandler::class);
$errorHandler->expects($this->once())
->method('requestNotFound')
->willReturn(Response::json(['error' => 'Not Found'])->withStatus(404));
$errorHandler->method('__invoke')
->will(
$this->returnCallback(
function (ServerRequestInterface $request, callable $next) {
return $next($request);
}
)
);
$app = $this->createAppWithoutLogger($errorHandler);

$request = new ServerRequest('GET', 'http://localhost/invalid');

$response = $app($request);
assert($response instanceof ResponseInterface);

$this->assertEquals(404, $response->getStatusCode());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
$this->assertStringMatchesFormat("{%a}", (string) $response->getBody());
}

private function createAppWithoutLogger(callable ...$middleware): App
{
$app = new App(...$middleware);
Expand Down