334 lines
8.8 KiB
PHP
Executable File
334 lines
8.8 KiB
PHP
Executable File
<?php
|
|
|
|
namespace AlibabaCloud\Client\Request;
|
|
|
|
use Exception;
|
|
use AlibabaCloud\Client\Support\Stringy;
|
|
use RuntimeException;
|
|
use AlibabaCloud\Client\SDK;
|
|
use AlibabaCloud\Client\Encode;
|
|
use AlibabaCloud\Client\Accept;
|
|
use AlibabaCloud\Client\Support\Path;
|
|
use AlibabaCloud\Client\Support\Sign;
|
|
use AlibabaCloud\Client\Filter\Filter;
|
|
use AlibabaCloud\Client\Support\Arrays;
|
|
use AlibabaCloud\Client\Filter\ApiFilter;
|
|
use AlibabaCloud\Client\Credentials\StsCredential;
|
|
use AlibabaCloud\Client\Exception\ClientException;
|
|
use AlibabaCloud\Client\Exception\ServerException;
|
|
use AlibabaCloud\Client\Credentials\AccessKeyCredential;
|
|
use AlibabaCloud\Client\Credentials\BearerTokenCredential;
|
|
use AlibabaCloud\Client\Request\Traits\DeprecatedRoaTrait;
|
|
|
|
/**
|
|
* RESTful ROA Request.
|
|
*
|
|
* @package AlibabaCloud\Client\Request
|
|
* @method setParameter()
|
|
*/
|
|
class RoaRequest extends Request
|
|
{
|
|
use DeprecatedRoaTrait;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
public $pathPattern = '/';
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
public $pathParameters = [];
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $dateTimeFormat = "D, d M Y H:i:s \G\M\T";
|
|
|
|
/**
|
|
* Resolve request parameter.
|
|
*
|
|
* @throws ClientException
|
|
* @throws Exception
|
|
*/
|
|
public function resolveParameter()
|
|
{
|
|
$this->resolveQuery();
|
|
$this->resolveHeaders();
|
|
$this->resolveBody();
|
|
$this->resolveUri();
|
|
$this->resolveSignature();
|
|
}
|
|
|
|
private function resolveQuery()
|
|
{
|
|
if (!isset($this->options['query']['Version'])) {
|
|
$this->options['query']['Version'] = $this->version;
|
|
}
|
|
}
|
|
|
|
private function resolveBody()
|
|
{
|
|
// If the body has already been specified, it will not be resolved.
|
|
if (isset($this->options['body'])) {
|
|
return;
|
|
}
|
|
|
|
if (!isset($this->options['form_params'])) {
|
|
return;
|
|
}
|
|
|
|
// Merge data, compatible with parameters set from constructor.
|
|
$params = Arrays::merge(
|
|
[
|
|
$this->data,
|
|
$this->options['form_params']
|
|
]
|
|
);
|
|
|
|
$this->encodeBody($params);
|
|
|
|
unset($this->options['form_params']);
|
|
}
|
|
|
|
/**
|
|
* Determine the body format based on the Content-Type and calculate the MD5 value.
|
|
*
|
|
* @param array $params
|
|
*/
|
|
private function encodeBody(array $params)
|
|
{
|
|
if (Stringy::contains($this->options['headers']['Content-Type'], 'application/json', false)) {
|
|
$this->options['body'] = json_encode($params);
|
|
$this->options['headers']['Content-MD5'] = base64_encode(md5($this->options['body'], true));
|
|
|
|
return;
|
|
}
|
|
|
|
$this->options['body'] = Encode::create($params)->ksort()->toString();
|
|
$this->options['headers']['Content-MD5'] = base64_encode(md5($this->options['body'], true));
|
|
$this->options['headers']['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
|
|
}
|
|
|
|
/**
|
|
* @throws ClientException
|
|
* @throws ServerException
|
|
* @throws Exception
|
|
*/
|
|
private function resolveHeaders()
|
|
{
|
|
$this->options['headers']['x-acs-version'] = $this->version;
|
|
$this->options['headers']['x-acs-region-id'] = $this->realRegionId();
|
|
$this->options['headers']['Date'] = gmdate($this->dateTimeFormat);
|
|
|
|
$signature = $this->httpClient()->getSignature();
|
|
$this->options['headers']['x-acs-signature-method'] = $signature->getMethod();
|
|
$this->options['headers']['x-acs-signature-nonce'] = Sign::uuid($this->product . $this->action);
|
|
$this->options['headers']['x-acs-signature-version'] = $signature->getVersion();
|
|
if ($signature->getType()) {
|
|
$this->options['headers']['x-acs-signature-type'] = $signature->getType();
|
|
}
|
|
|
|
$this->resolveAccept();
|
|
$this->resolveContentType();
|
|
$this->resolveSecurityToken();
|
|
$this->resolveBearerToken();
|
|
}
|
|
|
|
/**
|
|
* @throws ClientException
|
|
* @throws Exception
|
|
*/
|
|
private function resolveSignature()
|
|
{
|
|
$this->options['headers']['Authorization'] = $this->signature();
|
|
}
|
|
|
|
/**
|
|
* If accept is not specified, it is determined by format.
|
|
*/
|
|
private function resolveAccept()
|
|
{
|
|
if (!isset($this->options['headers']['Accept'])) {
|
|
$this->options['headers']['Accept'] = Accept::create($this->format)->toString();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If the Content-Type is not specified, it is determined according to accept.
|
|
*/
|
|
private function resolveContentType()
|
|
{
|
|
if (!isset($this->options['headers']['Content-Type'])) {
|
|
$this->options['headers']['Content-Type'] = "{$this->options['headers']['Accept']}; charset=utf-8";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws ClientException
|
|
* @throws ServerException
|
|
*/
|
|
private function resolveSecurityToken()
|
|
{
|
|
if (!$this->credential() instanceof StsCredential) {
|
|
return;
|
|
}
|
|
|
|
if (!$this->credential()->getSecurityToken()) {
|
|
return;
|
|
}
|
|
|
|
$this->options['headers']['x-acs-security-token'] = $this->credential()->getSecurityToken();
|
|
}
|
|
|
|
/**
|
|
* @throws ClientException
|
|
* @throws ServerException
|
|
*/
|
|
private function resolveBearerToken()
|
|
{
|
|
if ($this->credential() instanceof BearerTokenCredential) {
|
|
$this->options['headers']['x-acs-bearer-token'] = $this->credential()->getBearerToken();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sign the request message.
|
|
*
|
|
* @return string
|
|
* @throws ClientException
|
|
* @throws ServerException
|
|
*/
|
|
private function signature()
|
|
{
|
|
/**
|
|
* @var AccessKeyCredential $credential
|
|
*/
|
|
$credential = $this->credential();
|
|
$access_key_id = $credential->getAccessKeyId();
|
|
$signature = $this->httpClient()
|
|
->getSignature()
|
|
->sign(
|
|
$this->stringToSign(),
|
|
$credential->getAccessKeySecret()
|
|
);
|
|
|
|
return "acs $access_key_id:$signature";
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
private function resolveUri()
|
|
{
|
|
$path = Path::assign($this->pathPattern, $this->pathParameters);
|
|
|
|
$this->uri = $this->uri->withPath($path)
|
|
->withQuery(
|
|
$this->queryString()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function stringToSign()
|
|
{
|
|
$request = new \GuzzleHttp\Psr7\Request(
|
|
$this->method,
|
|
$this->uri,
|
|
$this->options['headers']
|
|
);
|
|
|
|
return Sign::roaString($request);
|
|
}
|
|
|
|
/**
|
|
* @return bool|string
|
|
*/
|
|
private function queryString()
|
|
{
|
|
$query = isset($this->options['query'])
|
|
? $this->options['query']
|
|
: [];
|
|
|
|
return Encode::create($query)->ksort()->toString();
|
|
}
|
|
|
|
/**
|
|
* Set path parameter by name.
|
|
*
|
|
* @param string $name
|
|
* @param string $value
|
|
*
|
|
* @return RoaRequest
|
|
* @throws ClientException
|
|
*/
|
|
public function pathParameter($name, $value)
|
|
{
|
|
Filter::name($name);
|
|
|
|
if ($value === '') {
|
|
throw new ClientException(
|
|
'Value cannot be empty',
|
|
SDK::INVALID_ARGUMENT
|
|
);
|
|
}
|
|
|
|
$this->pathParameters[$name] = $value;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set path pattern.
|
|
*
|
|
* @param string $pattern
|
|
*
|
|
* @return self
|
|
* @throws ClientException
|
|
*/
|
|
public function pathPattern($pattern)
|
|
{
|
|
ApiFilter::pattern($pattern);
|
|
|
|
$this->pathPattern = $pattern;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Magic method for set or get request parameters.
|
|
*
|
|
* @param string $name
|
|
* @param mixed $arguments
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function __call($name, $arguments)
|
|
{
|
|
if (strncmp($name, 'get', 3) === 0) {
|
|
$parameter_name = \mb_strcut($name, 3);
|
|
|
|
return $this->__get($parameter_name);
|
|
}
|
|
|
|
if (strncmp($name, 'with', 4) === 0) {
|
|
$parameter_name = \mb_strcut($name, 4);
|
|
$this->__set($parameter_name, $arguments[0]);
|
|
$this->pathParameters[$parameter_name] = $arguments[0];
|
|
|
|
return $this;
|
|
}
|
|
|
|
if (strncmp($name, 'set', 3) === 0) {
|
|
$parameter_name = \mb_strcut($name, 3);
|
|
$with_method = "with$parameter_name";
|
|
|
|
throw new RuntimeException("Please use $with_method instead of $name");
|
|
}
|
|
|
|
throw new RuntimeException('Call to undefined method ' . __CLASS__ . '::' . $name . '()');
|
|
}
|
|
}
|