PHP code example of tiny-blocks / http-error-handler
1. Go to this page and download the library: Download tiny-blocks/http-error-handler library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
tiny-blocks / http-error-handler example snippets
declare(strict_types=1);
use DomainException;
use InvalidArgumentException;
use RuntimeException;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
use TinyBlocks\Http\ErrorHandler\ExceptionMappingTable;
final readonly class ApplicationExceptionMapping implements ExceptionMapping
{
public function mappings(): ExceptionMappingTable
{
return ExceptionMappingTable::create()
->when(exceptionClass: InvalidArgumentException::class)
->mapsTo(code: 'INVALID_INPUT', status: 400, message: 'The request payload is invalid.')
->whenAny(exceptionClasses: [DomainException::class, RuntimeException::class])
->mapsTo(code: 'BUSINESS_FAILURE', status: 422, message: 'The operation could not be completed.')
->whenSubclassOf(baseException: RuntimeException::class)
->mapsTo(code: 'RUNTIME_FAMILY', status: 500, message: 'A runtime error occurred.');
}
}
declare(strict_types=1);
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
# Build the middleware with the declared mapping.
$middleware = ErrorMiddleware::create()
->withMapping(mapping: new ApplicationExceptionMapping())
->build();
declare(strict_types=1);
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
# The mappings are supplied by the consumer.
$write = new WriteExceptionMapping();
$read = new ReadExceptionMapping();
# Compose both mappings under one middleware.
$middleware = ErrorMiddleware::create()
->withMappings($write, $read)
->build();
declare(strict_types=1);
use RuntimeException;
use Throwable;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
use TinyBlocks\Http\ErrorHandler\ExceptionMappingTable;
use TinyBlocks\Http\ErrorHandler\MappedError;
final readonly class GatewayExceptionMapping implements ExceptionMapping
{
public function mappings(): ExceptionMappingTable
{
return ExceptionMappingTable::create()
->when(exceptionClass: RuntimeException::class)
->resolvesWith(
resolver: fn(Throwable $exception): MappedError => new MappedError(
code: 'GATEWAY_UNAVAILABLE',
status: 502,
message: $exception->getMessage()
)
);
}
}
declare(strict_types=1);
use Slim\Exception\HttpNotFoundException;
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
# The mapping is supplied by the consumer and declares nothing about routing.
$mapping = /** @var ExceptionMapping */ null;
$middleware = ErrorMiddleware::create()
->withMapping(mapping: $mapping)
->build();
# A request for a path with no route reaches the middleware as HttpNotFoundException, whose code is 404.
# The response is 404 {"code":"NOT_FOUND","message":"Not Found."} instead of a 500.
declare(strict_types=1);
use Psr\Http\Message\ServerRequestInterface;
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
use TinyBlocks\Http\ErrorHandler\ErrorPayload;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
# The mapping is supplied by the consumer.
$mapping = /** @var ExceptionMapping */ null;
# Answer in the reader's language, falling back to what the mapping declared.
$middleware = ErrorMiddleware::create()
->withMapping(mapping: $mapping)
->withMessage(resolver: static function (ErrorPayload $payload, ServerRequestInterface $request): string {
$curated = Messages::curatedFor(code: $payload->code);
return is_null($curated) ? $payload->message : $curated;
})
->build();
declare(strict_types=1);
use Psr\Log\LoggerInterface;
use TinyBlocks\Http\ErrorHandler\ErrorHandlingSettings;
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
# The logger and the mapping are supplied by the consumer.
$logger = /** @var LoggerInterface */ null;
$mapping = /** @var ExceptionMapping */ null;
# Enable error logging with full details, but keep stack traces out of the response.
$middleware = ErrorMiddleware::create()
->withLogger(logger: $logger)
->withMapping(mapping: $mapping)
->withSettings(settings: ErrorHandlingSettings::from(
logErrors: true,
logErrorDetails: true,
displayErrorDetails: false
))
->build();
declare(strict_types=1);
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
# The mapping is supplied by the consumer.
$mapping = /** @var ExceptionMapping */ null;
# Disable the fallback so that unmapped exceptions rethrow.
$middleware = ErrorMiddleware::create()
->withMapping(mapping: $mapping)
->withFallbackOnUnmapped(fallbackOnUnmapped: false)
->build();
declare(strict_types=1);
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
use TinyBlocks\Http\ErrorHandler\ErrorReporter;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
use TinyBlocks\Http\ErrorHandler\ReportedError;
# The mapping and the provider client are supplied by the consumer.
$mapping = /** @var ExceptionMapping */ null;
$client = /** @var ErrorTrackingClient */ null;
# One reporter adapts one provider. This one forwards only what no rule described.
final readonly class ErrorTrackingReporter implements ErrorReporter
{
public function __construct(private ErrorTrackingClient $client)
{
}
public function report(ReportedError $error): void
{
if ($error->wasMapped()) {
return;
}
$this->client->capture(
exception: $error->exception,
correlationId: $error->correlationId?->toString()
);
}
}
# Register as many reporters as there are providers to notify, one withReporter call per provider.
$middleware = ErrorMiddleware::create()
->withMapping(mapping: $mapping)
->withReporter(reporter: new ErrorTrackingReporter(client: $client))
->build();
declare(strict_types=1);
use TinyBlocks\Http\ErrorHandler\ReportingContext;
final class UpstreamUnavailable extends RuntimeException implements ReportingContext
{
public function __construct(string $message, private readonly string $service)
{
parent::__construct(message: $message);
}
public function reportingTags(): array
{
return ['service' => $this->service];
}
}
declare(strict_types=1);
use TinyBlocks\Http\ErrorHandler\PrioritizedError;
use TinyBlocks\Http\ErrorHandler\ReportingPriority;
final class PaymentTimedOut extends RuntimeException implements PrioritizedError
{
public function reportingPriority(): ReportingPriority
{
return ReportingPriority::CRITICAL;
}
}
declare(strict_types=1);
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TinyBlocks\Http\ErrorHandler\ReportingTags;
final readonly class RequireMembership implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$organizationId = $request->getHeaderLine('Organization-Id');
ReportingTags::from(request: $request)?->add(key: 'organization_id', value: $organizationId);
return $handler->handle($request);
}
}
declare(strict_types=1);
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
use TinyBlocks\Http\ErrorHandler\ExceptionMapping;
use TinyBlocks\Http\ErrorHandler\Reporters\SentryReporter;
# The mapping and the deployment values are supplied by the consumer.
$mapping = /** @var ExceptionMapping */ null;
$dsn = /** @var string */ '';
$release = /** @var string */ '';
$environment = /** @var string */ '';
$middleware = ErrorMiddleware::create()
->withMapping(mapping: $mapping)
->withReporter(
reporter: SentryReporter::initializedWith(
dsn: $dsn,
release: $release,
environment: $environment
)
)
->build();
declare(strict_types=1);
use Psr\Http\Message\ServerRequestInterface;
use Slim\Routing\RouteContext;
use TinyBlocks\Http\ErrorHandler\ErrorMiddleware;
use TinyBlocks\Http\ErrorHandler\RouteMiddleware;
# The middleware and the application are supplied by the consumer.
$middleware = /** @var ErrorMiddleware */ null;
$application = /** @var \Slim\App */ null;
# Registered first, so it runs closest to the route.
$application->add(RouteMiddleware::resolvedBy(
resolver: static fn(ServerRequestInterface $request): ?string
=> RouteContext::fromRequest($request)->getRoute()?->getPattern()
));
# The router above it, and the error middleware above the router, which is what keeps a 404 reaching it.
$application->addRoutingMiddleware();
$application->add($middleware);
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.