lcobucci / error-handling-middleware
兼容RFC 7807的PSR-15中间件
Requires
- php: ^8.0
- ext-json: *
- fig/http-message-util: ^1.1
- lcobucci/content-negotiation-middleware: ^3.1
- psr/http-factory: ^1.0
- psr/http-message: ^1.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^3.0
Requires (Dev)
- infection/infection: ^0.26
- laminas/laminas-diactoros: ^2.8
- lcobucci/coding-standard: ^8.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^1.4
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpstan/phpstan-strict-rules: ^1.1
- phpunit/phpunit: ^9.5
- 1.5.x-dev
- 1.4.x-dev
- 1.4.0
- 1.3.x-dev
- 1.3.0
- 1.2.x-dev
- 1.2.0
- 1.1.0
- 1.0.0
- dev-dependabot/composer/phpstan/phpstan-1.10.3
- dev-dependabot/composer/phpunit/php-code-coverage-9.2.25
- dev-dependabot/composer/phpstan/phpstan-phpunit-1.3.10
- dev-dependabot/composer/phpunit/phpunit-9.6.4
- dev-dependabot/composer/symfony/finder-5.4.21
- dev-dependabot/composer/symfony/string-5.4.21
- dev-dependabot/github_actions/actions/cache-3.2.6
- dev-dependabot/composer/phpstan/phpstan-deprecation-rules-1.1.2
- dev-dependabot/composer/phpstan/phpstan-strict-rules-1.5.0
- dev-dependabot/composer/phpstan/phpdoc-parser-1.16.1
- dev-dependabot/github_actions/ridedott/merge-me-action-2.10.43
- dev-dependabot/github_actions/shivammathur/setup-php-2.24.0
- dev-dependabot/composer/nikic/php-parser-4.15.3
- dev-dependabot/composer/doctrine/instantiator-1.5.0
- dev-dependabot/composer/laminas/laminas-diactoros-2.24.0
- dev-dependabot/composer/sanmai/pipeline-6.3
- dev-dependabot/composer/composer/pcre-3.1.0
- dev-dependabot/composer/symfony/polyfill-intl-normalizer-1.27.0
- dev-dependabot/composer/symfony/polyfill-ctype-1.27.0
- dev-dependabot/composer/symfony/polyfill-php80-1.27.0
- dev-dependabot/composer/symfony/polyfill-mbstring-1.27.0
- dev-dependabot/composer/symfony/polyfill-php73-1.27.0
- dev-dependabot/composer/symfony/polyfill-intl-grapheme-1.27.0
- dev-renovate/configure
This package is auto-updated.
Last update: 2024-08-30 01:23:20 UTC
README
动机
有很多PHP实现支持RFC 7807,甚至提供PSR-15中间件。然而,其中大多数——如果不是全部——将内容协商、日志记录和格式化与错误处理混合在一起。有些甚至强迫你抛出特定类型的异常才能使其工作。
我认为这不是最佳的设计决策,我们需要更多的灵活性来解决此问题。
安装
此包可在Packagist上找到,我们建议您使用Composer进行安装
composer require lcobucci/error-handling-middleware
用法
为了使用此包,您必须将中间件添加到您的管道中,配置所需的行为(调试信息策略和状态码提取策略)。
设置完成后,您将能够将错误/异常转换为正确的HTTP响应。
中间件位置
此包提供用于处理错误的两个中间件:错误日志和错误转换。
它们设计用于在HTTP中间件管道的开始处使用,紧接在内容协商中间件之后。
<?php use Lcobucci\ContentNegotiation\ContentTypeMiddleware; use Lcobucci\ErrorHandling\ErrorConversionMiddleware; use Lcobucci\ErrorHandling\ErrorLoggingMiddleware; // In a Laminas Mezzio application, it would look like this: $application->pipe(ContentTypeMiddleware::fromRecommendedSettings( /* ... */ )); // Very first middleware $application->pipe(new ErrorConversionMiddleware( /* ... */ )); $application->pipe(new ErrorLoggingMiddleware( /* ... */ )); // all other middleware.
这样我们就可以按正确的顺序进行日志记录和转换,将内容协商和格式化委托给使用配置的格式化程序的ContentTypeMiddleware
。
重要
ErrorConversionMiddleware
使用 UnformattedResponse
让 ContentTypeMiddleware
执行格式化。请确保您已为MIME类型 application/problem+json
和/或 application/problem+xml
配置了格式化程序。
它还使错误/异常在响应的 error
属性中可用,因此您可以通过使用位于 ErrorConversionMiddleware
和 ContentTypeMiddleware
之间的另一个中间件来访问它(如果需要的话)。
配置转换中间件的行为
您可以使用两个扩展点来做到这一点:调试信息策略和状态码提取策略。
您还可以通过在您的异常中实现某些接口来配置响应体属性。
调试信息策略
这定义了响应体中的 _debug
属性应该如何生成。我们提供了两个默认实现——一个是为生产模式设计的,另一个是为开发模式设计的。
要配置此策略,您必须将所需实现(或自定义实现)作为 ErrorConversionMiddleware
构造函数的第二个参数传递。
要提供自己的实现,您需要创建一个实现 DebugInfoStrategy
接口的新类。
状态码提取策略
这定义了如何将错误/异常转换为HTTP状态码。我们为此提供了一个基于类映射的单个默认实现。
要配置此策略,您必须将所需实现(或自定义实现)作为 ErrorConversionMiddleware
构造函数的第三个参数传递。
要提供自己的实现,您需要创建一个实现 StatusCodeExtractionStrategy
接口的新类。
默认类映射
默认映射使用该包中的标记接口来执行此类转换。如果错误/异常没有实现任何标记接口,则将使用错误/异常代码(当它不同于零时),或者回退到状态代码500(内部服务器错误)。
默认映射是
Lcobucci\ErrorHandling\Problem\InvalidRequest
->400
Lcobucci\ErrorHandling\Problem\AuthorizationRequired
->401
Lcobucci\ErrorHandling\Problem\Forbidden
->403
Lcobucci\ErrorHandling\Problem\ResourceNotFound
->404
Lcobucci\ErrorHandling\Problem\Conflict
->409
Lcobucci\ErrorHandling\Problem\ResourceNoLongerAvailable
->410
Lcobucci\ErrorHandling\Problem\UnprocessableRequest
->422
Lcobucci\ErrorHandling\Problem\ServiceUnavailable
->503
这允许我们创建自己的异常,它们将自动转换为正确的状态代码
<?php declare(strict_types=1); namespace My\Fancy\App\UserManagement; use Lcobucci\ErrorHandling\Problem\ResourceNotFound; use RuntimeException; final class UserNotFound extends RuntimeException implements ResourceNotFound { }
重要:您不应该实现超过一个标记接口,否则您可能会得到意外结果。
自定义响应体属性
使用此库,您可以修改生成的响应的 type
和 title
属性,并且还可以向其中添加新成员。
这是通过实现 Typed
、Titled
和/或 Detailed
接口来完成的——您不一定需要实现所有这些接口,只需要实现您想要的那些。
以下示例显示了如何表示 RFC 7807 中的其中一个示例
<?php declare(strict_types=1); namespace My\Fancy\App\UserManagement; use Lcobucci\ErrorHandling\Problem\Forbidden; use Lcobucci\ErrorHandling\Problem\Typed; use Lcobucci\ErrorHandling\Problem\Titled; use Lcobucci\ErrorHandling\Problem\Detailed; use RuntimeException; use function sprintf; final class InsufficientCredit extends RuntimeException implements Forbidden, Typed, Titled, Detailed { private $currentBalance; public static function forPurchase(int $currentBalance, int $cost): self { $exception = new self(sprintf('Your current balance is %d, but that costs %d.', $currentBalance, $cost)); $exception->currentBalance = $currentBalance; return $exception; } public function getTypeUri(): string { return 'https://example.com/probs/out-of-credit'; } public function getTitle(): string { return 'You do not have enough credit.'; } /** @inheritDoc */ public function getExtraDetails(): array { return ['balance' => $this->currentBalance]; // you might add "instance" and "accounts" too :) } }
许可证
MIT,请参阅 LICENSE。