Request.php 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. namespace AlibabaCloud\Credentials\Request;
  3. use AlibabaCloud\Credentials\Credentials;
  4. use AlibabaCloud\Credentials\EcsRamRoleCredential;
  5. use AlibabaCloud\Credentials\Helper;
  6. use AlibabaCloud\Credentials\RamRoleArnCredential;
  7. use AlibabaCloud\Credentials\Signature\ShaHmac1Signature;
  8. use AlibabaCloud\Credentials\Signature\ShaHmac256WithRsaSignature;
  9. use Exception;
  10. use GuzzleHttp\Client;
  11. use GuzzleHttp\HandlerStack;
  12. use GuzzleHttp\Middleware;
  13. use GuzzleHttp\Psr7\Uri;
  14. use AlibabaCloud\Tea\Response;
  15. use Psr\Http\Message\ResponseInterface;
  16. /**
  17. * RESTful RPC Request.
  18. */
  19. class Request
  20. {
  21. /**
  22. * Request Connect Timeout
  23. */
  24. const CONNECT_TIMEOUT = 5;
  25. /**
  26. * Request Timeout
  27. */
  28. const TIMEOUT = 10;
  29. /**
  30. * @var array
  31. */
  32. private static $config = [];
  33. /**
  34. * @var array
  35. */
  36. public $options = [];
  37. /**
  38. * @var Uri
  39. */
  40. public $uri;
  41. /**
  42. * @var EcsRamRoleCredential|RamRoleArnCredential
  43. */
  44. protected $credential;
  45. /**
  46. * @var ShaHmac256WithRsaSignature|ShaHmac1Signature
  47. */
  48. protected $signature;
  49. /**
  50. * Request constructor.
  51. */
  52. public function __construct()
  53. {
  54. $this->uri = (new Uri())->withScheme('https');
  55. $this->options['http_errors'] = false;
  56. $this->options['connect_timeout'] = self::CONNECT_TIMEOUT;
  57. $this->options['timeout'] = self::TIMEOUT;
  58. // Turn on debug mode based on environment variable.
  59. if (strtolower(Helper::env('DEBUG')) === 'sdk') {
  60. $this->options['debug'] = true;
  61. }
  62. }
  63. /**
  64. * @return ResponseInterface
  65. * @throws Exception
  66. */
  67. public function request()
  68. {
  69. $this->options['query']['Format'] = 'JSON';
  70. $this->options['query']['SignatureMethod'] = $this->signature->getMethod();
  71. $this->options['query']['SignatureVersion'] = $this->signature->getVersion();
  72. $this->options['query']['SignatureNonce'] = self::uuid(json_encode($this->options['query']));
  73. $this->options['query']['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
  74. $this->options['query']['Signature'] = $this->signature->sign(
  75. self::signString('GET', $this->options['query']),
  76. $this->credential->getOriginalAccessKeySecret() . '&'
  77. );
  78. return self::createClient()->request('GET', (string)$this->uri, $this->options);
  79. }
  80. /**
  81. * @param string $salt
  82. *
  83. * @return string
  84. */
  85. public static function uuid($salt)
  86. {
  87. return md5($salt . uniqid(md5(microtime(true)), true));
  88. }
  89. /**
  90. * @param string $method
  91. * @param array $parameters
  92. *
  93. * @return string
  94. */
  95. public static function signString($method, array $parameters)
  96. {
  97. ksort($parameters);
  98. $canonicalized = '';
  99. foreach ($parameters as $key => $value) {
  100. $canonicalized .= '&' . self::percentEncode($key) . '=' . self::percentEncode($value);
  101. }
  102. return $method . '&%2F&' . self::percentEncode(substr($canonicalized, 1));
  103. }
  104. /**
  105. * @param string $string
  106. *
  107. * @return null|string|string[]
  108. */
  109. private static function percentEncode($string)
  110. {
  111. $result = rawurlencode($string);
  112. $result = str_replace(['+', '*'], ['%20', '%2A'], $result);
  113. $result = preg_replace('/%7E/', '~', $result);
  114. return $result;
  115. }
  116. /**
  117. * @return Client
  118. * @throws Exception
  119. */
  120. public static function createClient()
  121. {
  122. if (Credentials::hasMock()) {
  123. $stack = HandlerStack::create(Credentials::getMock());
  124. } else {
  125. $stack = HandlerStack::create();
  126. }
  127. $stack->push(Middleware::mapResponse(static function (ResponseInterface $response) {
  128. return new Response($response);
  129. }));
  130. self::$config['handler'] = $stack;
  131. return new Client(self::$config);
  132. }
  133. }