You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
6.0 KiB
266 lines
6.0 KiB
3 weeks ago
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace App\Utils\Traits;
|
||
|
|
||
|
use GuzzleHttp\Client;
|
||
|
use GuzzleHttp\Handler\MockHandler;
|
||
|
use GuzzleHttp\HandlerStack;
|
||
|
use GuzzleHttp\Psr7\Response;
|
||
|
use InvalidArgumentException;
|
||
|
use JsonException;
|
||
|
use Psr\Http\Message\ResponseInterface;
|
||
|
|
||
|
trait HttpRequest
|
||
|
{
|
||
|
/**
|
||
|
* Http client.
|
||
|
*
|
||
|
* @var Client|null
|
||
|
*/
|
||
|
protected ?Client $httpClient = null;
|
||
|
|
||
|
/**
|
||
|
* Mock handler.
|
||
|
*
|
||
|
* @var MockHandler|null
|
||
|
*/
|
||
|
protected ?MockHandler $mockHandler = null;
|
||
|
|
||
|
/**
|
||
|
* Http header
|
||
|
*
|
||
|
* @var array<string, string>
|
||
|
*/
|
||
|
private array $httpHeader = [];
|
||
|
|
||
|
/**
|
||
|
* Http client options.
|
||
|
*
|
||
|
* @var array<string, mixed>
|
||
|
*/
|
||
|
protected array $httpOptions = [
|
||
|
'base_uri' => '',
|
||
|
'timeout' => 0,
|
||
|
'connect_timeout' => 0,
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* Send a GET request.
|
||
|
*
|
||
|
* @param string $endpoint 请求路由
|
||
|
* @param array<string, mixed> $query GET参数
|
||
|
* @param array<string, mixed> $headers 请求header头
|
||
|
*
|
||
|
* @return mixed
|
||
|
*
|
||
|
* @throws JsonException
|
||
|
*/
|
||
|
public function get(string $endpoint, array $query = [], array $headers = []): mixed
|
||
|
{
|
||
|
return $this->request('GET', $endpoint, [
|
||
|
'headers' => $headers,
|
||
|
'query' => $query,
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Send a POST request.
|
||
|
*
|
||
|
* @param string $endpoint 请求路由
|
||
|
* @param string|array<string, mixed> $data 请求数据
|
||
|
* @param array<string, mixed> $options options选项
|
||
|
*
|
||
|
* @return mixed
|
||
|
* @throws JsonException
|
||
|
*/
|
||
|
public function post(string $endpoint, string|array $data, array $options = []): mixed
|
||
|
{
|
||
|
if (!is_array($data)) {
|
||
|
$options['body'] = $data;
|
||
|
} else {
|
||
|
$options['form_params'] = $data;
|
||
|
}
|
||
|
|
||
|
return $this->request('POST', $endpoint, $options);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Send request.
|
||
|
*
|
||
|
* @param string $method 请求方法
|
||
|
* @param string $endpoint 请求路由
|
||
|
* @param array<string, mixed> $options options选项
|
||
|
*
|
||
|
* @return mixed
|
||
|
*
|
||
|
* @throws JsonException
|
||
|
*/
|
||
|
public function request(string $method, string $endpoint, array $options = []): mixed
|
||
|
{
|
||
|
return $this->unwrapResponse($this->getHttpClient()->{$method}($endpoint, $options));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Convert response.
|
||
|
*
|
||
|
* @param ResponseInterface $response 返回的response对象
|
||
|
*
|
||
|
* @return mixed
|
||
|
*
|
||
|
* @throws JsonException
|
||
|
*/
|
||
|
public function unwrapResponse(ResponseInterface $response): mixed
|
||
|
{
|
||
|
$contentType = $response->getHeaderLine('Content-Type');
|
||
|
$contents = $response->getBody()->getContents();
|
||
|
|
||
|
if (false !== stripos($contentType, 'json') || stripos($contentType, 'javascript')) {
|
||
|
return json_decode($contents, true, 512, JSON_THROW_ON_ERROR);
|
||
|
}
|
||
|
|
||
|
if (false !== stripos($contentType, 'xml')) {
|
||
|
return json_decode(
|
||
|
json_encode(
|
||
|
simplexml_load_string($contents, 'SimpleXMLElement', LIBXML_NOCDATA),
|
||
|
JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE
|
||
|
),
|
||
|
true,
|
||
|
512,
|
||
|
JSON_THROW_ON_ERROR
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $contents;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set http client.
|
||
|
*
|
||
|
* @param Client $client client请求客户端
|
||
|
*
|
||
|
* @return self
|
||
|
*/
|
||
|
public function setHttpClient(Client $client): self
|
||
|
{
|
||
|
$this->httpClient = $client;
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get http client.
|
||
|
*
|
||
|
* @return Client
|
||
|
*/
|
||
|
public function getHttpClient(): Client
|
||
|
{
|
||
|
if (is_null($this->httpClient)) {
|
||
|
$this->httpClient = $this->getDefaultHttpClient();
|
||
|
}
|
||
|
|
||
|
return $this->httpClient;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get default http client.
|
||
|
*
|
||
|
* @return Client
|
||
|
*/
|
||
|
public function getDefaultHttpClient(): Client
|
||
|
{
|
||
|
return new Client($this->getOptions());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* set mock Handler
|
||
|
*
|
||
|
* @param array<int, Response> $mock
|
||
|
*
|
||
|
* @return self
|
||
|
*/
|
||
|
public function setMockHandler(array $mock): self
|
||
|
{
|
||
|
array_walk($mock, static function ($value) {
|
||
|
if (!is_subclass_of($value, ResponseInterface::class)) {
|
||
|
throw new InvalidArgumentException(
|
||
|
$value::class . ' must be an instance of ' . ResponseInterface::class
|
||
|
);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$this->mockHandler = new MockHandler($mock);
|
||
|
$handlerStack = HandlerStack::create($this->mockHandler);
|
||
|
$this->setHttpOptions(['handler' => $handlerStack]);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get mock handler
|
||
|
*
|
||
|
* @return MockHandler|null
|
||
|
*/
|
||
|
public function getMockHandler(): ?MockHandler
|
||
|
{
|
||
|
return $this->mockHandler;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get default options.
|
||
|
*
|
||
|
* @return array<string, mixed>
|
||
|
*/
|
||
|
public function getOptions(): array
|
||
|
{
|
||
|
return $this->getHttpOptions();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set http header.
|
||
|
*
|
||
|
* @param array<string, string> $httpHeader
|
||
|
*
|
||
|
* @return self
|
||
|
*/
|
||
|
public function setHttpHeader(array $httpHeader): self
|
||
|
{
|
||
|
$this->httpHeader = array_merge($httpHeader, $this->httpHeader);
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get http header.
|
||
|
*
|
||
|
* @return array<string, string>
|
||
|
*/
|
||
|
public function getHttpHeader(): array
|
||
|
{
|
||
|
return $this->httpHeader;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set http options.
|
||
|
*
|
||
|
* @param array<string, HandlerStack|string> $httpOptions
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function setHttpOptions(array $httpOptions): void
|
||
|
{
|
||
|
$this->httpOptions = array_merge($this->httpOptions, $httpOptions);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get http options.
|
||
|
*
|
||
|
* @return array<string, mixed>
|
||
|
*/
|
||
|
public function getHttpOptions(): array
|
||
|
{
|
||
|
return $this->httpOptions;
|
||
|
}
|
||
|
}
|