Skip to content
Merged
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
23 changes: 9 additions & 14 deletions config/pipeline.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
use Api\App\Middleware\AuthorizationMiddleware;
use Api\App\Middleware\ContentNegotiationMiddleware;
use Api\App\Middleware\DeprecationMiddleware;
use Api\App\Middleware\ResponseMiddleware;
use Dot\ErrorHandler\ErrorHandlerInterface;
use Dot\ResponseHeader\Middleware\ResponseHeaderMiddleware;
use Mezzio\Application;
use Mezzio\Cors\Middleware\CorsMiddleware;
Expand All @@ -24,9 +22,9 @@
use Mezzio\Router\Middleware\RouteMiddleware;

return function (Application $app): void {
// The error handler should be the first (most outer) middleware to catch
// all Exceptions.
$app->pipe(ErrorHandlerInterface::class);
// This middleware must be the outest layer because - on error occurrence - it will:
// - call \Dot\ErrorHandler\ErrorHandlerInterface::class
// - return ProblemDetails response
$app->pipe(ProblemDetailsMiddleware::class);

$app->pipe(BodyParamsMiddleware::class);
Expand All @@ -38,15 +36,14 @@
// - pre-conditions
// - modifications to outgoing responses
//
// Piped Middleware may be either callables or service names. Middleware may
// also be passed as an array; each item in the array must resolve to
// middleware eventually (i.e., callable or service name).
// Piped Middleware may be either callables or service names.
// Middleware may also be passed as an array; each item in the array must resolve to middleware eventually
// (i.e., callable or service name).
//
// Middleware can be attached to specific paths, allowing you to mix and match
// applications under a common domain. The handlers in each middleware
// attached this way will see a URI with the matched path segment removed.
// Middleware can be attached to specific paths, allowing you to mix and match applications under a common domain.
// The handlers in each middleware attached this way will see a URI with the matched path segment removed.
//
// i.e., path of "/api/member/profile" only passes "/member/profile" to $apiMiddleware
// For example, the path of "/api/member/profile" only passes "/member/profile" to $apiMiddleware
// - $app->pipe('/api', $apiMiddleware);
// - $app->pipe('/docs', $apiDocMiddleware);
// - $app->pipe('/files', $filesMiddleware);
Expand Down Expand Up @@ -83,8 +80,6 @@
// - route-based validation
// - etc.

$app->pipe(ResponseMiddleware::class);

// Register the dispatch middleware in the middleware pipeline
$app->pipe(DispatchMiddleware::class);
// At this point, if no Response is returned by any middleware, the
Expand Down
5 changes: 3 additions & 2 deletions src/App/src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

use Api\App\Command\TokenGenerateCommand;
use Api\App\Factory\HandlerDelegatorFactory;
use Api\App\Factory\ProblemDetailsDelegatorFactory;
use Api\App\Handler\GetIndexResourceHandler;
use Api\App\Handler\PostErrorReportResourceHandler;
use Api\App\Middleware\AuthenticationMiddleware;
use Api\App\Middleware\AuthorizationMiddleware;
use Api\App\Middleware\ContentNegotiationMiddleware;
use Api\App\Middleware\DeprecationMiddleware;
use Api\App\Middleware\ErrorReportPermissionMiddleware;
use Api\App\Middleware\ResponseMiddleware;
use Api\App\Service\ErrorReportService;
use Api\App\Service\ErrorReportServiceInterface;
use Dot\DependencyInjection\Factory\AttributedServiceFactory;
Expand All @@ -23,6 +23,7 @@
use Mezzio\Authentication\OAuth2\OAuth2Adapter;
use Mezzio\Hal\Metadata\RouteBasedCollectionMetadata;
use Mezzio\Hal\Metadata\RouteBasedResourceMetadata;
use Mezzio\ProblemDetails\ProblemDetailsMiddleware;
use Mezzio\Template\TemplateRendererInterface;
use Mezzio\Twig\TwigEnvironmentFactory;
use Mezzio\Twig\TwigExtension;
Expand All @@ -47,14 +48,14 @@ private function getDependencies(): array
Application::class => [RoutesDelegator::class],
GetIndexResourceHandler::class => [HandlerDelegatorFactory::class],
PostErrorReportResourceHandler::class => [HandlerDelegatorFactory::class],
ProblemDetailsMiddleware::class => [ProblemDetailsDelegatorFactory::class],
],
'factories' => [
AuthenticationMiddleware::class => AttributedServiceFactory::class,
AuthorizationMiddleware::class => AttributedServiceFactory::class,
ContentNegotiationMiddleware::class => AttributedServiceFactory::class,
DeprecationMiddleware::class => AttributedServiceFactory::class,
ErrorReportPermissionMiddleware::class => AttributedServiceFactory::class,
ResponseMiddleware::class => AttributedServiceFactory::class,
GetIndexResourceHandler::class => AttributedServiceFactory::class,
PostErrorReportResourceHandler::class => AttributedServiceFactory::class,
ErrorReportService::class => AttributedServiceFactory::class,
Expand Down
53 changes: 53 additions & 0 deletions src/App/src/Factory/ProblemDetailsDelegatorFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Api\App\Factory;

use Api\App\Exception\RuntimeException;
use Core\App\Message;
use Dot\ErrorHandler\ErrorHandlerInterface;
use Dot\ErrorHandler\LogErrorHandler;
use Mezzio\ProblemDetails\ProblemDetailsMiddleware;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ServerRequestInterface;
use Throwable;

use function assert;

class ProblemDetailsDelegatorFactory
{
/**
* @param class-string $name
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
* @throws RuntimeException
*/
public function __invoke(
ContainerInterface $container,
string $name,
callable $callback
): ProblemDetailsMiddleware {
if (! $container->has(ErrorHandlerInterface::class)) {
throw RuntimeException::create(Message::serviceNotFound(ErrorHandlerInterface::class));
}

$problemDetailsMiddleware = $callback();
assert($problemDetailsMiddleware instanceof ProblemDetailsMiddleware);

$errorHandler = $container->get(ErrorHandlerInterface::class);
assert($errorHandler instanceof LogErrorHandler);

$listener = function (Throwable $throwable, RequestInterface $request) use ($errorHandler) {
assert($request instanceof ServerRequestInterface);
$errorHandler->handleThrowable($throwable, $request);
};

$problemDetailsMiddleware->attachListener($listener);

return $problemDetailsMiddleware;
}
}
41 changes: 0 additions & 41 deletions src/App/src/Middleware/ResponseMiddleware.php

This file was deleted.

Loading