Protobuf.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <?php
  2. namespace App\Module\AppGame\Tools;
  3. use App\Module\AppGame\Events\ProtobufResponseEvent;
  4. use Google\Protobuf\Internal\Message;
  5. use Illuminate\Support\Facades\Event;
  6. use Uraus\Kku\Response;
  7. /**
  8. * protobuf 助手函数
  9. *
  10. */
  11. class Protobuf
  12. {
  13. /**
  14. * 进行 Response返回类型处理
  15. * @param Response $response
  16. * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Foundation\Application|\Illuminate\Http\JsonResponse|\Illuminate\Http\Response|object
  17. */
  18. public static function response(Response $response)
  19. {
  20. $httpRequest = request();
  21. // 触发 ProtobufResponse 返回前事件
  22. Event::dispatch(new ProtobufResponseEvent($response));
  23. // 根据请求的 Accept 头决定响应格式
  24. $acceptHeader = $httpRequest->header('Accept');
  25. $contentType = $httpRequest->header('Content-Type');
  26. $ContentTypeBase64 = $httpRequest->header('Content-Type-Base64', 0);
  27. $ContentTypeBin = $httpRequest->header('Content-Type-Bin', 0);
  28. $forceJson = $httpRequest->header('Force-Json', 0);
  29. // 记录响应信息,便于调试
  30. \Illuminate\Support\Facades\Log::debug('Proto响应信息', [
  31. 'Accept' => $acceptHeader,
  32. 'Content-Type' => $contentType,
  33. 'Content-Type-Base64' => $ContentTypeBase64,
  34. 'Content-Type-Bin' => $ContentTypeBin,
  35. 'Force-Json' => $forceJson,
  36. 'response_size' => strlen($response->serializeToString()),
  37. 'response_json_size' => strlen($response->serializeToJsonString())
  38. ]);
  39. // 强制返回JSON格式(用于调试或客户端不支持二进制解析时)
  40. if ($forceJson) {
  41. return response()->json(
  42. self::protobufToArray($response)
  43. )->header('Content-Type', 'application/json');
  44. }
  45. // 返回Base64编码的Protobuf数据
  46. if ($ContentTypeBase64) {
  47. $base64Data = base64_encode($response->serializeToString());
  48. return response($base64Data)
  49. ->header('Content-Type', 'application/x-protobuf-base64');
  50. }
  51. // 返回JSON格式(当客户端请求JSON或发送JSON请求时)
  52. if ($ContentTypeBin == 0) {
  53. if (stripos($acceptHeader, 'json') !== false || stripos($contentType, 'json') !== false) {
  54. return response()->json(
  55. self::protobufToArray($response)
  56. );
  57. }
  58. }
  59. // 返回二进制Protobuf格式(默认)
  60. $binaryData = $response->serializeToString();
  61. return response($binaryData)
  62. ->header('Content-Type', 'application/x-protobuf');
  63. }
  64. /**
  65. * 将 Protobuf 消息对象转换为数组
  66. * @param Message $message Protobuf 消息对象
  67. * @return array
  68. */
  69. protected static function protobufToArray(Message $message): array
  70. {
  71. $json = $message->serializeToJsonString();
  72. return json_decode($json, true);
  73. }
  74. }