Skip to content

Commit

Permalink
implement ErrorFilter and add to middlewares in HordeCore
Browse files Browse the repository at this point in the history
  • Loading branch information
midahp authored and Ralf Lang committed Oct 25, 2023
1 parent f237507 commit d0096c9
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
61 changes: 57 additions & 4 deletions src/Middleware/ErrorFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

namespace Horde\Core\Middleware;

use Horde;
use Horde\Http\ResponseFactory;
use Horde\Http\StreamFactory;
use Horde_ErrorHandler;
use Horde_Registry;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Horde_Registry;
use Horde_Application;
use Throwable;

/**
* ErrorFilter middleware
Expand All @@ -31,9 +35,58 @@
*/
class ErrorFilter implements MiddlewareInterface
{
protected Horde_Registry $registry;
protected ResponseFactory $responseFactory;
protected StreamFactory $streamFactory;

public function __construct(
Horde_Registry $registry,
ResponseFactory $responseFactory,
StreamFactory $streamFactory
) {
$this->registry = $registry;
$this->responseFactory = $responseFactory;
$this->streamFactory = $streamFactory;
}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
// TODO:
return $handler->handle($request);
try {
return $handler->handle($request);
} catch (Throwable $throwable) {
Horde::log($throwable, 'EMERG');
return $this->getErrorResponse($request, $throwable);
}
}

protected function getErrorResponse(ServerRequestInterface $request, Throwable $throwable): ResponseInterface
{
$isAdmin = $this->registry->isAdmin();
$acceptsJson = in_array('application/json', array_map(fn($val) => strtolower($val), $request->getHeader('Accept')));
if ($acceptsJson){
return $this->getJsonResponse($throwable, $isAdmin);
} else {
return $this->getHtmlResponse($throwable, $isAdmin);
}
}

protected function getJsonResponse(Throwable $throwable, bool $isAdmin = false): ResponseInterface
{
$json = json_encode([
'message' => $throwable->getMessage(),
'code' => $throwable->getCode(),
'trace' => $isAdmin ? $throwable->getTrace() : [],
]);
$stream = $this->streamFactory->createStream($json);
return $this->responseFactory->createResponse(500, 'Internal Server Error')
->withBody($stream)
->withHeader('Content-Type', 'application/json');
}

protected function getHtmlResponse(Throwable $throwable, bool $isAdmin = false): ResponseInterface
{
$stream = $this->streamFactory->createStream(Horde_ErrorHandler::getHtmlForError($throwable, $isAdmin));
return $this->responseFactory->createResponse(500, 'Internal Server Error')
->withBody($stream);
}
}
8 changes: 5 additions & 3 deletions src/Middleware/HordeCore.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,15 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
$injector->setInstance(ResponseFactoryInterface::class, new ResponseFactory());
}


// Detect correct app
$registry = $injector->getInstance('Horde_Registry');
$request = $request->withAttribute('registry', $registry);
// First middleware should be ErrorFilter to catch all errors
$handler->addMiddleware(new ErrorFilter($registry, new ResponseFactory(), new StreamFactory()));
// Detect correct app
$handler->addMiddleware(new AppFinder($registry, new ResponseFactory(), new StreamFactory()));
// Find route inside detected app
$handler->addMiddleware(new AppRouter($registry, $injector->get('Horde_Routes_Mapper'), $injector));

$request = $request->withAttribute('registry', $registry);
return $handler->handle($request);
}
}

0 comments on commit d0096c9

Please sign in to comment.