DefaultAcsClient.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <?php
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. class DefaultAcsClient implements IAcsClient
  21. {
  22. /**
  23. * @var IClientProfile
  24. */
  25. public $iClientProfile;
  26. /**
  27. * @var bool
  28. */
  29. public $__urlTestFlag__;
  30. /**
  31. * @var LocationService
  32. */
  33. private $locationService;
  34. /**
  35. * @var RamRoleArnService
  36. */
  37. private $ramRoleArnService;
  38. /**
  39. * @var EcsRamRoleService
  40. */
  41. private $ecsRamRoleService;
  42. /**
  43. * DefaultAcsClient constructor.
  44. *
  45. * @param $iClientProfile
  46. */
  47. public function __construct($iClientProfile)
  48. {
  49. $this->iClientProfile = $iClientProfile;
  50. $this->__urlTestFlag__ = false;
  51. $this->locationService = new LocationService($this->iClientProfile);
  52. if ($this->iClientProfile->isRamRoleArn()) {
  53. $this->ramRoleArnService = new RamRoleArnService($this->iClientProfile);
  54. }
  55. if ($this->iClientProfile->isEcsRamRole()) {
  56. $this->ecsRamRoleService = new EcsRamRoleService($this->iClientProfile);
  57. }
  58. }
  59. /**
  60. * @param $request
  61. * @param null $iSigner
  62. * @param null $credential
  63. * @param bool $autoRetry
  64. * @param int $maxRetryNumber
  65. *
  66. * @return mixed|SimpleXMLElement
  67. * @throws ClientException
  68. * @throws ServerException
  69. */
  70. public function getAcsResponse($request,
  71. $iSigner = null,
  72. $credential = null,
  73. $autoRetry = true,
  74. $maxRetryNumber = 3)
  75. {
  76. $httpResponse = $this->doActionImpl($request, $iSigner, $credential, $autoRetry, $maxRetryNumber);
  77. $respObject = $this->parseAcsResponse($httpResponse->getBody(), $request->getAcceptFormat());
  78. if (false === $httpResponse->isSuccess()) {
  79. $this->buildApiException($respObject, $httpResponse->getStatus(), $request);
  80. }
  81. return $respObject;
  82. }
  83. /**
  84. * @param AcsRequest $request
  85. * @param null $iSigner
  86. * @param null $credential
  87. * @param bool $autoRetry
  88. * @param int $maxRetryNumber
  89. *
  90. * @return HttpResponse
  91. * @throws ClientException
  92. */
  93. private function doActionImpl($request, $iSigner = null, $credential = null, $autoRetry = true, $maxRetryNumber = 3)
  94. {
  95. if (null == $this->iClientProfile
  96. && (null == $iSigner || null == $credential
  97. || null == $request->getRegionId()
  98. || null == $request->getAcceptFormat())) {
  99. throw new ClientException('No active profile found.', 'SDK.InvalidProfile');
  100. }
  101. if (null == $iSigner) {
  102. $iSigner = $this->iClientProfile->getSigner();
  103. }
  104. if (null == $credential) {
  105. $credential = $this->iClientProfile->getCredential();
  106. }
  107. if ($this->iClientProfile->isRamRoleArn()) {
  108. $credential = $this->ramRoleArnService->getSessionCredential();
  109. }
  110. if ($this->iClientProfile->isEcsRamRole()) {
  111. $credential = $this->ecsRamRoleService->getSessionCredential();
  112. }
  113. if (null == $credential) {
  114. throw new ClientException('Incorrect user credentials.', 'SDK.InvalidCredential');
  115. }
  116. $request = $this->prepareRequest($request);
  117. // Get the domain from the Location Service by speicified `ServiceCode` and `RegionId`.
  118. $domain = null;
  119. if (null != $request->getLocationServiceCode()) {
  120. $domain =
  121. $this->locationService->findProductDomain($request->getRegionId(),
  122. $request->getLocationServiceCode(),
  123. $request->getLocationEndpointType(),
  124. $request->getProduct());
  125. }
  126. if ($domain == null) {
  127. $domain = EndpointProvider::findProductDomain($request->getRegionId(), $request->getProduct());
  128. }
  129. if (null == $domain) {
  130. throw new ClientException('Can not find endpoint to access.', 'SDK.InvalidRegionId');
  131. }
  132. $requestUrl = $request->composeUrl($iSigner, $credential, $domain);
  133. if ($this->__urlTestFlag__) {
  134. throw new ClientException($requestUrl, 'URLTestFlagIsSet');
  135. }
  136. if (count($request->getDomainParameter()) > 0) {
  137. $httpResponse =
  138. HttpHelper::curl($requestUrl,
  139. $request->getMethod(),
  140. $request->getDomainParameter(),
  141. $request->getHeaders());
  142. } else {
  143. $httpResponse =
  144. HttpHelper::curl($requestUrl, $request->getMethod(), $request->getContent(), $request->getHeaders());
  145. }
  146. $retryTimes = 1;
  147. while (500 <= $httpResponse->getStatus() && $autoRetry && $retryTimes < $maxRetryNumber) {
  148. $requestUrl = $request->composeUrl($iSigner, $credential, $domain);
  149. if (count($request->getDomainParameter()) > 0) {
  150. $httpResponse =
  151. HttpHelper::curl($requestUrl,
  152. $request->getMethod(),
  153. $request->getDomainParameter(),
  154. $request->getHeaders());
  155. } else {
  156. $httpResponse =
  157. HttpHelper::curl($requestUrl,
  158. $request->getMethod(),
  159. $request->getContent(),
  160. $request->getHeaders());
  161. }
  162. $retryTimes++;
  163. }
  164. return $httpResponse;
  165. }
  166. /**
  167. * @param AcsRequest $request
  168. * @param null $iSigner
  169. * @param null $credential
  170. * @param bool $autoRetry
  171. * @param int $maxRetryNumber
  172. *
  173. * @return HttpResponse|mixed
  174. * @throws ClientException
  175. */
  176. public function doAction($request, $iSigner = null, $credential = null, $autoRetry = true, $maxRetryNumber = 3)
  177. {
  178. trigger_error('doAction() is deprecated. Please use getAcsResponse() instead.', E_USER_NOTICE);
  179. return $this->doActionImpl($request, $iSigner, $credential, $autoRetry, $maxRetryNumber);
  180. }
  181. /**
  182. * @param $request
  183. *
  184. * @return mixed
  185. */
  186. private function prepareRequest($request)
  187. {
  188. if (null == $request->getRegionId()) {
  189. $request->setRegionId($this->iClientProfile->getRegionId());
  190. }
  191. if (null == $request->getAcceptFormat()) {
  192. $request->setAcceptFormat($this->iClientProfile->getFormat());
  193. }
  194. if (null == $request->getMethod()) {
  195. $request->setMethod('GET');
  196. }
  197. return $request;
  198. }
  199. /**
  200. * @param object $respObject
  201. * @param int $httpStatus
  202. *
  203. * @param AcsRequest $request
  204. *
  205. * @throws ServerException
  206. */
  207. private function buildApiException($respObject, $httpStatus, AcsRequest $request)
  208. {
  209. $errorCode = 'UnknownServerError';
  210. $errorMessage = 'The server returned an error without a detailed message. ';
  211. $requestId = 'None';
  212. // Compatible with different results
  213. if (isset($respObject->Message, $respObject->Code, $respObject->RequestId)) {
  214. $errorCode = $respObject->Code;
  215. $errorMessage = $respObject->Message;
  216. $requestId = $respObject->RequestId;
  217. }
  218. if (isset($respObject->message, $respObject->code, $respObject->requestId)) {
  219. $errorCode = $respObject->code;
  220. $errorMessage = $respObject->message;
  221. $requestId = $respObject->requestId;
  222. }
  223. if (isset($respObject->errorMsg, $respObject->errorCode)) {
  224. $errorCode = $respObject->errorCode;
  225. $errorMessage = $respObject->errorMsg;
  226. }
  227. if ($httpStatus === 400 && $errorCode === 'SignatureDoesNotMatch'
  228. && strpos($errorMessage,
  229. $request->stringToBeSigned()) !== false) {
  230. $errorCode = 'InvalidAccessKeySecret';
  231. $errorMessage = 'Specified Access Key Secret is not valid.';
  232. }
  233. throw new ServerException(
  234. $errorMessage,
  235. $errorCode,
  236. $httpStatus,
  237. $requestId
  238. );
  239. }
  240. /**
  241. * @param $body
  242. * @param $format
  243. *
  244. * @return mixed|SimpleXMLElement
  245. */
  246. private function parseAcsResponse($body, $format)
  247. {
  248. if ('JSON' === $format) {
  249. $respObject = json_decode($body);
  250. } elseif ('XML' === $format) {
  251. $respObject = @simplexml_load_string($body);
  252. } elseif ('RAW' === $format) {
  253. $respObject = $body;
  254. }
  255. return $respObject;
  256. }
  257. }