AbstractProvider.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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\Nacos;
  12. use GuzzleHttp\Client;
  13. use GuzzleHttp\RequestOptions;
  14. use Hyperf\Codec\Json;
  15. use Hyperf\Nacos\Exception\RequestException;
  16. use Hyperf\Nacos\Provider\AccessToken;
  17. use Psr\Http\Message\ResponseInterface;
  18. use Psr\Http\Message\UriInterface;
  19. abstract class AbstractProvider
  20. {
  21. use AccessToken;
  22. public function __construct(protected Application $app, protected Config $config)
  23. {
  24. }
  25. public function request(string $method, string|UriInterface $uri, array $options = [])
  26. {
  27. if ($accessKey = $this->config->getAccessKey()) {
  28. $accessSecret = $this->config->getAccessSecret();
  29. if (str_contains($uri, '/ns/')) { // naming
  30. $options[RequestOptions::HEADERS]['ak'] = $accessKey;
  31. $signHeaders = $this->getNamingSignHeaders(
  32. $options[RequestOptions::QUERY]['groupName'] ?? '',
  33. $options[RequestOptions::QUERY]['serviceName'] ?? '',
  34. $accessSecret
  35. );
  36. foreach ($signHeaders as $header => $value) {
  37. $options[RequestOptions::HEADERS][$header] = $value;
  38. }
  39. } else { // config
  40. $options[RequestOptions::HEADERS]['Spas-AccessKey'] = $accessKey;
  41. $signHeaders = $this->getMseSignHeaders($options[RequestOptions::QUERY] ?? [], $accessSecret);
  42. foreach ($signHeaders as $header => $value) {
  43. $options[RequestOptions::HEADERS][$header] = $value;
  44. }
  45. }
  46. } else {
  47. if ($token = $this->getAccessToken()) {
  48. $options[RequestOptions::QUERY]['accessToken'] = $token;
  49. }
  50. }
  51. return $this->client()->request($method, $uri, $options);
  52. }
  53. public function client(): Client
  54. {
  55. $config = array_merge($this->config->getGuzzleConfig(), [
  56. 'base_uri' => $this->config->getBaseUri(),
  57. ]);
  58. return new Client($config);
  59. }
  60. protected function checkResponseIsOk(ResponseInterface $response): bool
  61. {
  62. if ($response->getStatusCode() !== 200) {
  63. return false;
  64. }
  65. return (string) $response->getBody() === 'ok';
  66. }
  67. protected function handleResponse(ResponseInterface $response): array
  68. {
  69. $statusCode = $response->getStatusCode();
  70. $contents = (string) $response->getBody();
  71. if ($statusCode !== 200) {
  72. throw new RequestException($contents, $statusCode);
  73. }
  74. return Json::decode($contents);
  75. }
  76. protected function filter(array $input): array
  77. {
  78. $result = [];
  79. foreach ($input as $key => $value) {
  80. if ($value !== null) {
  81. $result[$key] = $value;
  82. }
  83. }
  84. return $result;
  85. }
  86. protected function getMseSignHeaders(array $data, string $secretKey): array
  87. {
  88. $group = $data['group'] ?? '';
  89. $tenant = $data['tenant'] ?? '';
  90. $timeStamp = round(microtime(true) * 1000);
  91. $signStr = '';
  92. if ($tenant) {
  93. $signStr .= "{$tenant}+";
  94. }
  95. if ($group) {
  96. $signStr .= "{$group}+";
  97. }
  98. $signStr .= "{$timeStamp}";
  99. return [
  100. 'timeStamp' => $timeStamp,
  101. 'Spas-Signature' => base64_encode(hash_hmac('sha1', $signStr, $secretKey, true)),
  102. ];
  103. }
  104. protected function getNamingSignHeaders(string $groupName, string $serverName, string $secretKey): array
  105. {
  106. $timeStamp = round(microtime(true) * 1000);
  107. $signStr = $timeStamp;
  108. if (! empty($serverName)) {
  109. if (str_contains($serverName, '@@') || empty($groupName)) {
  110. $signStr .= "@@{$serverName}";
  111. } else {
  112. $signStr .= "@@{$groupName}@@{$serverName}";
  113. }
  114. }
  115. return [
  116. 'data' => $signStr,
  117. 'signature' => base64_encode(hash_hmac('sha1', $signStr, $secretKey, true)),
  118. ];
  119. }
  120. }