HasHttpRequests.php 5.6 KB

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