Files
hyperf_data/extend/Aether/PHP/Hyperf/Middleware/GatewayExceptionHandler.php
2025-09-28 14:51:38 +08:00

97 lines
3.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace Aether\Middleware;
use Aether\RpcException\BusinessException;
use Aether\RpcException\ErrorCode;
use Hyperf\Context\ApplicationContext;
use Hyperf\Context\Context;
use Hyperf\Contract\StdoutLoggerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Throwable;
use function Hyperf\support\env;
class GatewayExceptionHandler implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
Context::set(ServerRequestInterface::class, $request);
try {
return $handler->handle($request);
} catch (Throwable $e) {
// 尝试解析异常信息判断是否为RPC服务返回的业务异常
$parsed = $this->parseRpcException($e);
if ($parsed) {
// 转换为业务异常
throw new BusinessException(
$parsed['code'],
$parsed['message'],
$parsed['data'] ?? []
);
}
// 记录非业务异常日志
$logger = ApplicationContext::getContainer()->get(StdoutLoggerInterface::class);
$logger->error(sprintf('服务调用异常: %s', $e->getMessage()), [
'trace' => $e->getTraceAsString(),
'file' => $e->getFile(),
'line' => $e->getLine(),
]);
// 非业务异常,使用系统错误码
if ($e instanceof BusinessException) {
throw $e;
}
// 统一转换为系统错误
throw new BusinessException(
env('APP_ENV') === 'dev' ? $e->getMessage() : ErrorCode::getMessage(ErrorCode::RPC_CALL_ERROR),
ErrorCode::RPC_CALL_ERROR,
);
}
}
/**
* 解析RPC异常信息.
*/
private function parseRpcException(Throwable $e): ?array
{
try {
// 从异常消息中解析JSON数据
$message = $e->getMessage();
$data = json_decode($message, true);
// 检查是否为有效的JSON-RPC错误响应
if (json_last_error() === JSON_ERROR_NONE && isset($data['jsonrpc']) && $data['jsonrpc'] === '2.0') {
$error = $data['error'] ?? [];
// 检查是否包含业务异常标识
return [
'code' => $error['code'] ?? ErrorCode::RPC_CALL_ERROR,
'message' => $error['message'] ?? '服务调用异常',
'data' => $error['data'] ?? [],
];
// 普通RPC错误
}
// 检查是否为直接返回的错误数组
if (is_array($data) && isset($data['code'], $data['message'])) {
return $data;
}
} catch (Throwable $parseError) {
// 解析失败不影响主流程
}
return null;
}
}