HasHttpRequests.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <?php
  2. /*
  3. * This file is part of the overtrue/wechat.
  4. *
  5. * (c) overtrue <i@overtrue.me>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace App\Libs\TikTok\Kernel\Traits;
  11. use GuzzleHttp\Client;
  12. use GuzzleHttp\ClientInterface;
  13. use GuzzleHttp\Exception\GuzzleException;
  14. use GuzzleHttp\HandlerStack;
  15. use Psr\Http\Message\ResponseInterface;
  16. /**
  17. * Trait HasHttpRequests.
  18. *
  19. * @author overtrue <i@overtrue.me>
  20. */
  21. trait HasHttpRequests {
  22. use ResponseCastable;
  23. /**
  24. * @var ClientInterface
  25. */
  26. protected $httpClient;
  27. /**
  28. * @var array
  29. */
  30. protected $middlewares = [];
  31. /**
  32. * @var HandlerStack
  33. */
  34. protected $handlerStack;
  35. /**
  36. * @var array
  37. */
  38. protected static $defaults = [
  39. 'curl' => [
  40. CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
  41. ],
  42. ];
  43. /**
  44. * Set guzzle default settings.
  45. *
  46. * @param array $defaults
  47. */
  48. public static function setDefaultOptions(array $defaults = []): void {
  49. self::$defaults = $defaults;
  50. }
  51. /**
  52. * Return current guzzle default settings.
  53. *
  54. * @return array
  55. */
  56. public static function getDefaultOptions(): array {
  57. return self::$defaults;
  58. }
  59. /**
  60. * Set GuzzleHttp\Client.
  61. *
  62. * @param ClientInterface $httpClient
  63. *
  64. * @return $this
  65. */
  66. public function setHttpClient(ClientInterface $httpClient) {
  67. $this->httpClient = $httpClient;
  68. return $this;
  69. }
  70. /**
  71. * Return GuzzleHttp\ClientInterface instance.
  72. *
  73. * @return ClientInterface
  74. */
  75. public function getHttpClient(): ClientInterface {
  76. if (!($this->httpClient instanceof ClientInterface)) {
  77. if (property_exists($this, 'app') && $this->app['http_client']) {
  78. $this->httpClient = $this->app['http_client'];
  79. } else {
  80. $this->httpClient = new Client(['handler' => HandlerStack::create($this->getGuzzleHandler())]);
  81. }
  82. }
  83. return $this->httpClient;
  84. }
  85. /**
  86. * Add a middleware.
  87. *
  88. * @param callable $middleware
  89. * @param string|null $name
  90. *
  91. * @return $this
  92. */
  93. public function pushMiddleware(callable $middleware, string $name = null) {
  94. if (!is_null($name)) {
  95. $this->middlewares[$name] = $middleware;
  96. } else {
  97. array_push($this->middlewares, $middleware);
  98. }
  99. return $this;
  100. }
  101. /**
  102. * Return all middlewares.
  103. *
  104. * @return array
  105. */
  106. public function getMiddlewares(): array {
  107. return $this->middlewares;
  108. }
  109. /**
  110. * Make a request.
  111. *
  112. * @param string $url
  113. * @param string $method
  114. * @param array $options
  115. *
  116. * @return ResponseInterface
  117. *
  118. * @throws GuzzleException
  119. */
  120. public function request(string $url, string $method = 'GET', array $options = []): ResponseInterface {
  121. $method = strtoupper($method);
  122. $options = array_merge(self::$defaults, $options, ['handler' => $this->getHandlerStack()]);
  123. $options = $this->fixJsonIssue($options);
  124. if (property_exists($this, 'baseUri') && !is_null($this->baseUri)) {
  125. $options['base_uri'] = $this->baseUri;
  126. }
  127. $response = $this->getHttpClient()->request($method, $url, $options);
  128. $response->getBody()->rewind();
  129. return $response;
  130. }
  131. /**
  132. * @param HandlerStack $handlerStack
  133. *
  134. * @return $this
  135. */
  136. public function setHandlerStack(HandlerStack $handlerStack) {
  137. $this->handlerStack = $handlerStack;
  138. return $this;
  139. }
  140. /**
  141. * Build a handler stack.
  142. *
  143. * @return HandlerStack
  144. */
  145. public function getHandlerStack(): HandlerStack {
  146. if ($this->handlerStack) {
  147. return $this->handlerStack;
  148. }
  149. $this->handlerStack = HandlerStack::create($this->getGuzzleHandler());
  150. foreach ($this->middlewares as $name => $middleware) {
  151. $this->handlerStack->push($middleware, $name);
  152. }
  153. return $this->handlerStack;
  154. }
  155. /**
  156. * @param array $options
  157. *
  158. * @return array
  159. */
  160. protected function fixJsonIssue(array $options): array {
  161. if (isset($options['json']) && is_array($options['json'])) {
  162. $options['headers'] = array_merge($options['headers'] ?? [], ['Content-Type' => 'application/json']);
  163. if (empty($options['json'])) {
  164. $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_FORCE_OBJECT);
  165. } else {
  166. $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_UNESCAPED_UNICODE);
  167. }
  168. unset($options['json']);
  169. }
  170. return $options;
  171. }
  172. /**
  173. * Get guzzle handler.
  174. *
  175. * @return callable
  176. */
  177. protected function getGuzzleHandler(): callable {
  178. if (property_exists($this, 'app') && isset($this->app['guzzle_handler'])) {
  179. return is_string($handler = $this->app->raw('guzzle_handler'))
  180. ? new $handler()
  181. : $handler;
  182. }
  183. return \GuzzleHttp\choose_handler();
  184. }
  185. }