Files
hyperf_data/extend/Aether/PHP/Hyperf/RpcExceptionHandler.php
2025-09-26 17:27:15 +08:00

106 lines
3.4 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;
use Hyperf\Context\Context;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Psr\Http\Message\ResponseInterface;
use Throwable;
use function Hyperf\Support\env;
class RpcExceptionHandler extends ExceptionHandler
{
public function handle(Throwable $throwable, ResponseInterface $response): ResponseInterface
{
var_dump($throwable->getMessage());
try {
// 获取请求ID用于日志追踪
$requestId = Context::get('request_id', '');
// 从请求中获取可能的RPC ID
$rpcId = $this->getRpcIdFromRequest();
// 构建符合JSON-RPC 2.0规范的错误响应
$errorResponse = [
'jsonrpc' => '2.0',
'id' => $rpcId ?? $requestId,
'error' => [
'code' => $throwable->getCode() ?: -32603, // 默认服务器错误码
'message' => $throwable->getMessage() ?: 'Internal error',
'data' => [
'request_id' => $requestId,
'exception_type' => get_class($throwable),
// 开发环境下可以添加更多调试信息
'debug' => env('APP_ENV') === 'dev' ? [
'file' => $throwable->getFile(),
'line' => $throwable->getLine(),
] : null,
],
],
];
// JSON编码
$jsonResponse = json_encode($errorResponse, JSON_UNESCAPED_UNICODE);
// 检查JSON编码错误
if (json_last_error() !== JSON_ERROR_NONE) {
$jsonResponse = json_encode([
'jsonrpc' => '2.0',
'id' => $rpcId ?? $requestId,
'error' => [
'code' => -32603,
'message' => 'Failed to encode error response',
'data' => ['request_id' => $requestId],
],
]);
}
return $response
->withHeader('Content-Type', 'application/json')
->withBody(new SwooleStream((string) $jsonResponse));
} catch (Throwable $e) {
$fallbackResponse = json_encode([
'jsonrpc' => '2.0',
'id' => null,
'error' => [
'code' => -32603,
'message' => 'Fatal error occurred in exception handler',
'data' => ['original_error' => $throwable->getMessage()],
],
]);
return $response
->withHeader('Content-Type', 'application/json')
->withBody(new SwooleStream((string) $fallbackResponse));
}
}
public function isValid(Throwable $throwable): bool
{
return true;
}
/**
* 尝试从请求中获取RPC ID.
*/
private function getRpcIdFromRequest(): mixed
{
try {
$request = Context::get('hyperf.request');
if ($request) {
$body = $request->getParsedBody();
if (is_array($body) && isset($body['id'])) {
return $body['id'];
}
}
} catch (Throwable $e) {
// 获取失败时静默处理
}
return null;
}
}