452 lines
10 KiB
PHP
Executable File
452 lines
10 KiB
PHP
Executable File
<?php
|
|
|
|
namespace AlibabaCloud\Client\Request;
|
|
|
|
use AlibabaCloud\Client\AlibabaCloud;
|
|
use AlibabaCloud\Client\Credentials\Providers\CredentialsProvider;
|
|
use AlibabaCloud\Client\Encode;
|
|
use AlibabaCloud\Client\Exception\ClientException;
|
|
use AlibabaCloud\Client\Exception\ServerException;
|
|
use AlibabaCloud\Client\Filter\ApiFilter;
|
|
use AlibabaCloud\Client\Filter\ClientFilter;
|
|
use AlibabaCloud\Client\Filter\Filter;
|
|
use AlibabaCloud\Client\Filter\HttpFilter;
|
|
use AlibabaCloud\Client\Request\Traits\AcsTrait;
|
|
use AlibabaCloud\Client\Request\Traits\ClientTrait;
|
|
use AlibabaCloud\Client\Request\Traits\DeprecatedTrait;
|
|
use AlibabaCloud\Client\Request\Traits\RetryTrait;
|
|
use AlibabaCloud\Client\Result\Result;
|
|
use AlibabaCloud\Client\SDK;
|
|
use AlibabaCloud\Client\Traits\ArrayAccessTrait;
|
|
use AlibabaCloud\Client\Traits\HttpTrait;
|
|
use AlibabaCloud\Client\Traits\ObjectAccessTrait;
|
|
use AlibabaCloud\Client\Traits\RegionTrait;
|
|
use ArrayAccess;
|
|
use Exception;
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Exception\GuzzleException;
|
|
use GuzzleHttp\HandlerStack;
|
|
use GuzzleHttp\MessageFormatter;
|
|
use GuzzleHttp\Middleware;
|
|
use GuzzleHttp\Promise\PromiseInterface;
|
|
use GuzzleHttp\Psr7\Uri;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
|
|
/**
|
|
* Class Request
|
|
*
|
|
* @package AlibabaCloud\Client\Request
|
|
*
|
|
* @method string stringToSign()
|
|
* @method string resolveParameter()
|
|
*/
|
|
abstract class Request implements ArrayAccess
|
|
{
|
|
use DeprecatedTrait;
|
|
use HttpTrait;
|
|
use RegionTrait;
|
|
use ClientTrait;
|
|
use AcsTrait;
|
|
use ArrayAccessTrait;
|
|
use ObjectAccessTrait;
|
|
use RetryTrait;
|
|
|
|
/**
|
|
* Request Connect Timeout
|
|
*/
|
|
const CONNECT_TIMEOUT = 5;
|
|
|
|
/**
|
|
* Request Timeout
|
|
*/
|
|
const TIMEOUT = 10;
|
|
|
|
/**
|
|
* @var string HTTP Method
|
|
*/
|
|
public $method = 'GET';
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
public $format = 'JSON';
|
|
|
|
/**
|
|
* @var string HTTP Scheme
|
|
*/
|
|
protected $scheme = 'http';
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
public $client;
|
|
|
|
/**
|
|
* @var Uri
|
|
*/
|
|
public $uri;
|
|
|
|
/**
|
|
* @var array The original parameters of the request.
|
|
*/
|
|
public $data = [];
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
private $userAgent = [];
|
|
|
|
/**
|
|
* Request constructor.
|
|
*
|
|
* @param array $options
|
|
*
|
|
* @throws ClientException
|
|
*/
|
|
public function __construct(array $options = [])
|
|
{
|
|
$this->client = CredentialsProvider::getDefaultName();
|
|
$this->uri = new Uri();
|
|
$this->uri = $this->uri->withScheme($this->scheme);
|
|
$this->options['http_errors'] = false;
|
|
$this->options['connect_timeout'] = self::CONNECT_TIMEOUT;
|
|
$this->options['timeout'] = self::TIMEOUT;
|
|
|
|
// Turn on debug mode based on environment variable.
|
|
if (null !== \AlibabaCloud\Client\env('DEBUG') && strtolower(\AlibabaCloud\Client\env('DEBUG')) === 'sdk') {
|
|
$this->options['debug'] = true;
|
|
}
|
|
|
|
// Rewrite configuration if the user has a configuration.
|
|
if ($options !== []) {
|
|
$this->options($options);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
* @param string $value
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function appendUserAgent($name, $value)
|
|
{
|
|
$filter_name = Filter::name($name);
|
|
|
|
if (!UserAgent::isGuarded($filter_name)) {
|
|
$this->userAgent[$filter_name] = Filter::value($value);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param array $userAgent
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function withUserAgent(array $userAgent)
|
|
{
|
|
$this->userAgent = UserAgent::clean($userAgent);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set Accept format.
|
|
*
|
|
* @param string $format
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function format($format)
|
|
{
|
|
$this->format = ApiFilter::format($format);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param $contentType
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function contentType($contentType)
|
|
{
|
|
$this->options['headers']['Content-Type'] = HttpFilter::contentType($contentType);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string $accept
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function accept($accept)
|
|
{
|
|
$this->options['headers']['Accept'] = HttpFilter::accept($accept);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the request body.
|
|
*
|
|
* @param string $body
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function body($body)
|
|
{
|
|
$this->options['body'] = HttpFilter::body($body);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the json as body.
|
|
*
|
|
* @param array|object $content
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function jsonBody($content)
|
|
{
|
|
if (!\is_array($content) && !\is_object($content)) {
|
|
throw new ClientException(
|
|
'jsonBody only accepts an array or object',
|
|
SDK::INVALID_ARGUMENT
|
|
);
|
|
}
|
|
|
|
return $this->body(\json_encode($content));
|
|
}
|
|
|
|
/**
|
|
* Set the request scheme.
|
|
*
|
|
* @param string $scheme
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function scheme($scheme)
|
|
{
|
|
$this->scheme = HttpFilter::scheme($scheme);
|
|
$this->uri = $this->uri->withScheme($scheme);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the request host.
|
|
*
|
|
* @param string $host
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function host($host)
|
|
{
|
|
$this->uri = $this->uri->withHost(HttpFilter::host($host));
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string $method
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function method($method)
|
|
{
|
|
$this->method = HttpFilter::method($method);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param string $clientName
|
|
*
|
|
* @return $this
|
|
* @throws ClientException
|
|
*/
|
|
public function client($clientName)
|
|
{
|
|
$this->client = ClientFilter::clientName($clientName);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
* @throws ClientException
|
|
*/
|
|
public function isDebug()
|
|
{
|
|
if (isset($this->options['debug'])) {
|
|
return $this->options['debug'] === true;
|
|
}
|
|
|
|
if (isset($this->httpClient()->options['debug'])) {
|
|
return $this->httpClient()->options['debug'] === true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @throws ClientException
|
|
* @throws ServerException
|
|
*/
|
|
public function resolveOption()
|
|
{
|
|
$this->options['headers']['User-Agent'] = UserAgent::toString($this->userAgent);
|
|
|
|
$this->cleanQuery();
|
|
$this->cleanFormParams();
|
|
$this->resolveHost();
|
|
$this->resolveParameter();
|
|
|
|
if (isset($this->options['form_params'])) {
|
|
if (function_exists('\GuzzleHttp\Psr7\parse_query')) {
|
|
$this->options['form_params'] = \GuzzleHttp\Psr7\parse_query(
|
|
Encode::create($this->options['form_params'])->toString()
|
|
);
|
|
} else {
|
|
$this->options['form_params'] = \GuzzleHttp\Psr7\Query::parse(
|
|
Encode::create($this->options['form_params'])->toString()
|
|
);
|
|
}
|
|
}
|
|
|
|
$this->mergeOptionsIntoClient();
|
|
}
|
|
|
|
/**
|
|
* @return Result
|
|
* @throws ClientException
|
|
* @throws ServerException
|
|
*/
|
|
public function request()
|
|
{
|
|
$this->resolveOption();
|
|
$result = $this->response();
|
|
|
|
if ($this->shouldServerRetry($result)) {
|
|
return $this->request();
|
|
}
|
|
|
|
if (!$result->isSuccess()) {
|
|
throw new ServerException($result);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/***
|
|
* @return PromiseInterface
|
|
* @throws Exception
|
|
*/
|
|
public function requestAsync()
|
|
{
|
|
$this->resolveOption();
|
|
|
|
return self::createClient($this)->requestAsync(
|
|
$this->method,
|
|
(string)$this->uri,
|
|
$this->options
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
*
|
|
* @return Client
|
|
* @throws Exception
|
|
*/
|
|
public static function createClient(Request $request = null)
|
|
{
|
|
if (AlibabaCloud::hasMock()) {
|
|
$stack = HandlerStack::create(AlibabaCloud::getMock());
|
|
} else {
|
|
$stack = HandlerStack::create();
|
|
}
|
|
|
|
if (AlibabaCloud::isRememberHistory()) {
|
|
$stack->push(Middleware::history(AlibabaCloud::referenceHistory()));
|
|
}
|
|
|
|
if (AlibabaCloud::getLogger()) {
|
|
$stack->push(Middleware::log(
|
|
AlibabaCloud::getLogger(),
|
|
new MessageFormatter(AlibabaCloud::getLogFormat())
|
|
));
|
|
}
|
|
|
|
$stack->push(Middleware::mapResponse(static function (ResponseInterface $response) use ($request) {
|
|
return new Result($response, $request);
|
|
}));
|
|
|
|
self::$config['handler'] = $stack;
|
|
|
|
return new Client(self::$config);
|
|
}
|
|
|
|
/**
|
|
* @throws ClientException
|
|
* @throws Exception
|
|
*/
|
|
private function response()
|
|
{
|
|
try {
|
|
return self::createClient($this)->request(
|
|
$this->method,
|
|
(string)$this->uri,
|
|
$this->options
|
|
);
|
|
} catch (GuzzleException $exception) {
|
|
if ($this->shouldClientRetry($exception)) {
|
|
return $this->response();
|
|
}
|
|
throw new ClientException(
|
|
$exception->getMessage(),
|
|
SDK::SERVER_UNREACHABLE,
|
|
$exception
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove redundant Query
|
|
*
|
|
* @codeCoverageIgnore
|
|
*/
|
|
private function cleanQuery()
|
|
{
|
|
if (isset($this->options['query']) && $this->options['query'] === []) {
|
|
unset($this->options['query']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove redundant Headers
|
|
*
|
|
* @codeCoverageIgnore
|
|
*/
|
|
private function cleanFormParams()
|
|
{
|
|
if (isset($this->options['form_params']) && $this->options['form_params'] === []) {
|
|
unset($this->options['form_params']);
|
|
}
|
|
}
|
|
}
|