Files
wh-api/app/Exception/Handler/AppExceptionHandler.php
ykxiao 0b2299c427
Some checks failed
Build Docker / build (push) Has been cancelled
协程版仓库后端项目
2025-07-08 14:59:47 +08:00

98 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Exception\Handler;
use App\Exception\ApiException;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\RateLimit\Exception\RateLimitException;
use Hyperf\Validation\ValidationException;
use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use Throwable;
use function Hyperf\Support\env;
/**
* Author: ykxiao
* Date: 2025/6/3
* Time: 下午8:57
* Description: 默认异常处理
*
* (c) ykxiao <yk_9001@hotmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
class AppExceptionHandler extends ExceptionHandler
{
public function __construct(protected StdoutLoggerInterface $logger)
{
}
public function handle(Throwable $throwable, ResponseInterface $response): MessageInterface|ResponseInterface
{
$this->logException($throwable);
if ($throwable instanceof RateLimitException) {
return $this->handleRateLimitException($response);
}
return $this->handleOtherExceptions($throwable, $response);
}
public function isValid(Throwable $throwable): bool
{
return ! $throwable instanceof ApiException;
}
protected function createResponseBody($message, $code): StreamInterface
{
$data = [
'code' => $code,
'message' => $message,
];
return new SwooleStream(json_encode($data, JSON_UNESCAPED_UNICODE));
}
protected function logException(Throwable $throwable): void
{
$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
$this->logger->error($throwable->getTraceAsString());
}
protected function handleRateLimitException(ResponseInterface $response): ResponseInterface
{
$message = '触发请求频率限流规则';
return $response->withStatus(429)
->withHeader('Content-Type', 'application/json')
->withBody($this->createResponseBody($message, 429));
}
protected function handleOtherExceptions(Throwable $throwable, ResponseInterface $response): ResponseInterface
{
$message = $throwable->getMessage();
if (env('APP_ENV') === 'production' && ! $throwable instanceof ValidationException) {
return $response->withStatus(200)
->withHeader('Content-Type', 'application/json')
->withBody($this->createResponseBody($message, 0));
}
return $response->withHeader('Server', 'mes-auto')
->withStatus(200)
->withBody($this->createResponseBody($message, 0));
}
}