HttpServer.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * This file is part of Hyperf.
  5. *
  6. * @link https://www.hyperf.io
  7. * @document https://hyperf.wiki
  8. * @contact group@hyperf.io
  9. * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
  10. */
  11. namespace Hyperf\JsonRpc;
  12. use Hyperf\ExceptionHandler\ExceptionHandlerDispatcher;
  13. use Hyperf\HttpMessage\Server\Request as Psr7Request;
  14. use Hyperf\HttpMessage\Server\Response as Psr7Response;
  15. use Hyperf\HttpServer\Contract\CoreMiddlewareInterface;
  16. use Hyperf\HttpServer\ResponseEmitter;
  17. use Hyperf\HttpServer\Server;
  18. use Hyperf\JsonRpc\Exception\Handler\HttpExceptionHandler;
  19. use Hyperf\Rpc\Context as RpcContext;
  20. use Hyperf\Rpc\Protocol;
  21. use Hyperf\Rpc\ProtocolManager;
  22. use Hyperf\RpcServer\RequestDispatcher;
  23. use Hyperf\Utils\Context;
  24. use Psr\Container\ContainerInterface;
  25. use Psr\Http\Message\RequestInterface;
  26. use Psr\Http\Message\ResponseInterface;
  27. use Psr\Http\Message\ServerRequestInterface;
  28. use Swoole\Http\Request as SwooleRequest;
  29. use Swoole\Http\Response as SwooleResponse;
  30. class HttpServer extends Server
  31. {
  32. /**
  33. * @var Protocol
  34. */
  35. protected $protocol;
  36. /**
  37. * @var \Hyperf\Contract\PackerInterface
  38. */
  39. protected $packer;
  40. /**
  41. * @var \Hyperf\JsonRpc\ResponseBuilder
  42. */
  43. protected $responseBuilder;
  44. public function __construct(
  45. ContainerInterface $container,
  46. RequestDispatcher $dispatcher,
  47. ExceptionHandlerDispatcher $exceptionHandlerDispatcher,
  48. ResponseEmitter $responseEmitter,
  49. ProtocolManager $protocolManager
  50. ) {
  51. parent::__construct($container, $dispatcher, $exceptionHandlerDispatcher, $responseEmitter);
  52. $this->protocol = new Protocol($container, $protocolManager, 'jsonrpc-http');
  53. $this->packer = $this->protocol->getPacker();
  54. $this->responseBuilder = make(ResponseBuilder::class, [
  55. 'dataFormatter' => $this->protocol->getDataFormatter(),
  56. 'packer' => $this->packer,
  57. ]);
  58. }
  59. protected function getDefaultExceptionHandler(): array
  60. {
  61. return [
  62. HttpExceptionHandler::class,
  63. ];
  64. }
  65. protected function createCoreMiddleware(): CoreMiddlewareInterface
  66. {
  67. return new HttpCoreMiddleware($this->container, $this->protocol, $this->responseBuilder, $this->serverName);
  68. }
  69. protected function initRequestAndResponse(SwooleRequest $request, SwooleResponse $response): array
  70. {
  71. // Initialize PSR-7 Request and Response objects.
  72. $psr7Request = Psr7Request::loadFromSwooleRequest($request);
  73. Context::set(ResponseInterface::class, $psr7Response = new Psr7Response());
  74. if (! $this->isHealthCheck($psr7Request)) {
  75. if (strpos($psr7Request->getHeaderLine('content-type'), 'application/json') === false) {
  76. $psr7Response = $this->responseBuilder->buildErrorResponse($psr7Request, ResponseBuilder::PARSE_ERROR);
  77. }
  78. // @TODO Optimize the error handling of encode.
  79. $content = $this->packer->unpack($psr7Request->getBody()->getContents());
  80. if (! isset($content['jsonrpc'], $content['method'], $content['params'])) {
  81. $psr7Response = $this->responseBuilder->buildErrorResponse($psr7Request, ResponseBuilder::INVALID_REQUEST);
  82. }
  83. }
  84. $psr7Request = $psr7Request->withUri($psr7Request->getUri()->withPath($content['method'] ?? '/'))
  85. ->withParsedBody($content['params'] ?? null)
  86. ->withAttribute('data', $content ?? [])
  87. ->withAttribute('request_id', $content['id'] ?? null);
  88. $this->getContext()->setData($content['context'] ?? []);
  89. Context::set(ServerRequestInterface::class, $psr7Request);
  90. Context::set(ResponseInterface::class, $psr7Response);
  91. return [$psr7Request, $psr7Response];
  92. }
  93. protected function isHealthCheck(RequestInterface $request): bool
  94. {
  95. return $request->getHeaderLine('user-agent') === 'Consul Health Check';
  96. }
  97. protected function getContext()
  98. {
  99. return $this->container->get(RpcContext::class);
  100. }
  101. }