HttpServer.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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\Contract\PackerInterface;
  13. use Hyperf\ExceptionHandler\ExceptionHandlerDispatcher;
  14. use Hyperf\HttpServer\Contract\CoreMiddlewareInterface;
  15. use Hyperf\HttpServer\ResponseEmitter;
  16. use Hyperf\HttpServer\Server;
  17. use Hyperf\JsonRpc\Exception\Handler\HttpExceptionHandler;
  18. use Hyperf\Rpc\Context as RpcContext;
  19. use Hyperf\Rpc\Protocol;
  20. use Hyperf\Rpc\ProtocolManager;
  21. use Hyperf\RpcServer\RequestDispatcher;
  22. use Psr\Container\ContainerInterface;
  23. use Psr\Http\Message\RequestInterface;
  24. use Swow\Psr7\Message\ResponsePlusInterface;
  25. use Swow\Psr7\Message\ServerRequestPlusInterface;
  26. use function Hyperf\Support\make;
  27. class HttpServer extends Server
  28. {
  29. protected Protocol $protocol;
  30. protected PackerInterface $packer;
  31. protected ResponseBuilder $responseBuilder;
  32. public function __construct(
  33. ContainerInterface $container,
  34. RequestDispatcher $dispatcher,
  35. ExceptionHandlerDispatcher $exceptionHandlerDispatcher,
  36. ResponseEmitter $responseEmitter,
  37. ProtocolManager $protocolManager
  38. ) {
  39. parent::__construct($container, $dispatcher, $exceptionHandlerDispatcher, $responseEmitter);
  40. $this->protocol = new Protocol($container, $protocolManager, 'jsonrpc-http');
  41. $this->packer = $this->protocol->getPacker();
  42. $this->responseBuilder = make(ResponseBuilder::class, [
  43. 'dataFormatter' => $this->protocol->getDataFormatter(),
  44. 'packer' => $this->packer,
  45. ]);
  46. }
  47. protected function getDefaultExceptionHandler(): array
  48. {
  49. return [
  50. HttpExceptionHandler::class,
  51. ];
  52. }
  53. protected function createCoreMiddleware(): CoreMiddlewareInterface
  54. {
  55. return new HttpCoreMiddleware($this->container, $this->protocol, $this->responseBuilder, $this->serverName);
  56. }
  57. protected function initRequestAndResponse($request, $response): array
  58. {
  59. /**
  60. * @var ServerRequestPlusInterface $psr7Request
  61. * @var ResponsePlusInterface $psr7Response
  62. */
  63. [$psr7Request, $psr7Response] = parent::initRequestAndResponse($request, $response);
  64. if (! $this->isHealthCheck($psr7Request)) {
  65. if (! str_contains($psr7Request->getHeaderLine('content-type'), 'application/json')) {
  66. $psr7Response = $this->responseBuilder->buildErrorResponse($psr7Request, ResponseBuilder::PARSE_ERROR);
  67. }
  68. // @TODO Optimize the error handling of encode.
  69. $content = $this->packer->unpack((string) $psr7Request->getBody());
  70. if (! isset($content['jsonrpc'], $content['method'], $content['params'])) {
  71. $psr7Response = $this->responseBuilder->buildErrorResponse($psr7Request, ResponseBuilder::INVALID_REQUEST);
  72. }
  73. }
  74. $psr7Request = $psr7Request->setUri($psr7Request->getUri()->withPath($content['method'] ?? '/'))
  75. ->setParsedBody($content['params'] ?? null)
  76. ->setAttribute('data', $content ?? [])
  77. ->setAttribute('request_id', $content['id'] ?? null);
  78. $this->getContext()->setData($content['context'] ?? []);
  79. return [$psr7Request, $psr7Response];
  80. }
  81. protected function isHealthCheck(RequestInterface $request): bool
  82. {
  83. return $request->getHeaderLine('user-agent') === 'Consul Health Check';
  84. }
  85. protected function getContext()
  86. {
  87. return $this->container->get(RpcContext::class);
  88. }
  89. }