Protobuf.php 3.1 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. \Illuminate\Support\Facades\Log::debug('Proto响应信息-json', json_decode($response->serializeToJsonString(),true));
  40. // 强制返回JSON格式(用于调试或客户端不支持二进制解析时)
  41. if ($forceJson) {
  42. return response()->json(
  43. self::protobufToArray($response)
  44. )->header('Content-Type', 'application/json');
  45. }
  46. // 返回Base64编码的Protobuf数据
  47. if ($ContentTypeBase64) {
  48. $base64Data = base64_encode($response->serializeToString());
  49. return response($base64Data)
  50. ->header('Content-Type', 'text/plain');
  51. }
  52. // 返回JSON格式(当客户端请求JSON或发送JSON请求时)
  53. if ($ContentTypeBin == 0) {
  54. if (stripos($acceptHeader, 'json') !== false || stripos($contentType, 'json') !== false) {
  55. return response()->json(
  56. self::protobufToArray($response)
  57. );
  58. }
  59. }
  60. // 返回二进制Protobuf格式(默认)
  61. $binaryData = $response->serializeToString();
  62. return response($binaryData)
  63. ->header('Content-Type', 'application/x-protobuf');
  64. }
  65. /**
  66. * 将 Protobuf 消息对象转换为数组
  67. * @param Message $message Protobuf 消息对象
  68. * @return array
  69. */
  70. protected static function protobufToArray(Message $message): array
  71. {
  72. $json = $message->serializeToJsonString();
  73. return json_decode($json, true);
  74. }
  75. }