Skip to content

Commit a4cb187

Browse files
committed
Add test case
1 parent d014498 commit a4cb187

File tree

3 files changed

+216
-65
lines changed

3 files changed

+216
-65
lines changed
Lines changed: 169 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
/*
34
* Licensed to the Apache Software Foundation (ASF) under one
45
* or more contributor license agreements. See the NOTICE file
@@ -17,33 +18,87 @@
1718
* specific language governing permissions and limitations
1819
* under the License.
1920
*/
20-
class DefaultAcsClient implements IAcsClient
21+
22+
use GuzzleHttp\Client;
23+
use GuzzleHttp\Psr7\Request as HttpRequest;
24+
use Psr\Http\Message\ResponseInterface;
25+
26+
class DefaultAcsClient extends Client implements IAcsClient
2127
{
28+
2229
public $iClientProfile;
23-
public $__urlTestFlag__;
30+
2431
private $locationService;
25-
26-
public function __construct($iClientProfile)
32+
33+
/**
34+
* DefaultAcsClient constructor.
35+
* @param array $iClientProfile
36+
* @param array $config
37+
*/
38+
public function __construct($iClientProfile, array $config = [])
2739
{
2840
$this->iClientProfile = $iClientProfile;
29-
$this->__urlTestFlag__ = false;
3041
$this->locationService = new LocationService($this->iClientProfile);
42+
43+
parent::__construct(array_merge(['http_errors' => false], $config));
3144
}
32-
33-
public function getAcsResponse($request, $iSigner = null, $credential = null, $autoRetry = true, $maxRetryNumber = 3)
45+
46+
public function getAcsResponse(AcsRequest $request, $iSigner = null, $credential = null, $autoRetry = true, $maxRetryNumber = 3)
3447
{
3548
$httpResponse = $this->doActionImpl($request, $iSigner, $credential, $autoRetry, $maxRetryNumber);
36-
$respObject = $this->parseAcsResponse($httpResponse->getBody(), $request->getAcceptFormat());
37-
if (false == $httpResponse->isSuccess()) {
38-
$this->buildApiException($respObject, $httpResponse->getStatus());
49+
$respObject = self::parseAcsResponse($httpResponse);
50+
if (false == self::isSuccess($httpResponse)) {
51+
$this->buildApiException($respObject, $httpResponse->getStatusCode());
3952
}
4053
return $respObject;
4154
}
4255

56+
public static function isSuccess(ResponseInterface $response)
57+
{
58+
if (200 <= $response->getStatusCode() && 300 > $response->getStatusCode()) {
59+
return true;
60+
}
61+
return false;
62+
}
63+
4364
private function doActionImpl($request, $iSigner = null, $credential = null, $autoRetry = true, $maxRetryNumber = 3)
65+
{
66+
$httpRequest = $this->buildHttpRequest($request, $iSigner, $credential);
67+
$httpResponse = $this->send($httpRequest);
68+
69+
$retryTimes = 1;
70+
while (500 <= $httpResponse->getStatusCode() && $autoRetry && $retryTimes < $maxRetryNumber) {
71+
$httpRequest = $this->buildHttpRequest($request, $iSigner, $credential);
72+
$httpResponse = $this->send($httpRequest);
73+
$retryTimes++;
74+
}
75+
return $httpResponse;
76+
}
77+
78+
public function doAction($request, $iSigner = null, $credential = null, $autoRetry = true, $maxRetryNumber = 3)
79+
{
80+
trigger_error("doAction() is deprecated. Please use getAcsResponse() instead.", E_USER_NOTICE);
81+
return $this->doActionImpl($request, $iSigner, $credential, $autoRetry, $maxRetryNumber);
82+
}
83+
84+
private function prepareRequest($request)
85+
{
86+
if (null == $request->getRegionId()) {
87+
$request->setRegionId($this->iClientProfile->getRegionId());
88+
}
89+
if (null == $request->getAcceptFormat()) {
90+
$request->setAcceptFormat($this->iClientProfile->getFormat());
91+
}
92+
if (null == $request->getMethod()) {
93+
$request->setMethod("GET");
94+
}
95+
return $request;
96+
}
97+
98+
public function buildHttpRequest(AcsRequest $request, $iSigner = null, $credential = null)
4499
{
45100
if (null == $this->iClientProfile && (null == $iSigner || null == $credential
46-
|| null == $request->getRegionId() || null == $request->getAcceptFormat())) {
101+
|| null == $request->getRegionId() || null == $request->getAcceptFormat())) {
47102
throw new ClientException("No active profile found.", "SDK.InvalidProfile");
48103
}
49104
if (null == $iSigner) {
@@ -56,79 +111,128 @@ private function doActionImpl($request, $iSigner = null, $credential = null, $au
56111

57112
// Get the domain from the Location Service by speicified `ServiceCode` and `RegionId`.
58113
$domain = null;
59-
if (null != $request->getLocationServiceCode())
60-
{
61-
$domain = $this->locationService->findProductDomain($request->getRegionId(), $request->getLocationServiceCode(), $request->getLocationEndpointType(), $request->getProduct());
62-
}
63-
if ($domain == null)
64-
{
114+
if (null != $request->getLocationServiceCode()) {
115+
$domain = $this->locationService->findProductDomain(
116+
$request->getRegionId(),
117+
$request->getLocationServiceCode(),
118+
$request->getLocationEndpointType(),
119+
$request->getProduct()
120+
);
121+
}
122+
if ($domain == null) {
65123
$domain = EndpointProvider::findProductDomain($request->getRegionId(), $request->getProduct());
66124
}
67125

68126
if (null == $domain) {
69127
throw new ClientException("Can not find endpoint to access.", "SDK.InvalidRegionId");
70128
}
71-
$requestUrl = $request->composeUrl($iSigner, $credential, $domain);
72129

73-
if ($this->__urlTestFlag__) {
74-
throw new ClientException($requestUrl, "URLTestFlagIsSet");
75-
}
130+
return (new HttpRequest(
131+
$request->getMethod(),
132+
$request->composeUrl($iSigner, $credential, $domain),
133+
$request->getHeaders(),
134+
$this->getAcsRequestBody($request)
135+
))->withHeader('Content-Type', 'application/x-www-form-urlencoded')
136+
->withHeader('Accept', $this->convertStdHttpAccept($request->getAcceptFormat()));
137+
}
76138

77-
if (count($request->getDomainParameter())>0) {
78-
$httpResponse = HttpHelper::curl($requestUrl, $request->getMethod(), $request->getDomainParameter(), $request->getHeaders());
139+
/**
140+
* @param $format
141+
* @return string
142+
*/
143+
public function convertStdHttpAccept($format)
144+
{
145+
if ("JSON" == $format) {
146+
return 'application/json';
147+
} elseif ("XML" == $format) {
148+
return 'text/xml';
149+
} elseif ("RAW" == $format) {
150+
return '*/*';
79151
} else {
80-
$httpResponse = HttpHelper::curl($requestUrl, $request->getMethod(), $request->getContent(), $request->getHeaders());
152+
return '*/*';
81153
}
82-
83-
$retryTimes = 1;
84-
while (500 <= $httpResponse->getStatus() && $autoRetry && $retryTimes < $maxRetryNumber) {
85-
$requestUrl = $request->composeUrl($iSigner, $credential, $domain);
86-
87-
if (count($request->getDomainParameter())>0) {
88-
$httpResponse = HttpHelper::curl($requestUrl, $request->getMethod(), $request->getDomainParameter(), $request->getHeaders());
89-
} else {
90-
$httpResponse = HttpHelper::curl($requestUrl, $request->getMethod(), $request->getContent(), $request->getHeaders());
91-
}
92-
$retryTimes ++;
93-
}
94-
return $httpResponse;
95154
}
96-
97-
public function doAction($request, $iSigner = null, $credential = null, $autoRetry = true, $maxRetryNumber = 3)
155+
156+
/**
157+
* @param AcsRequest $request
158+
* @return string
159+
*/
160+
public function getAcsRequestBody(AcsRequest $request)
98161
{
99-
trigger_error("doAction() is deprecated. Please use getAcsResponse() instead.", E_USER_NOTICE);
100-
return $this->doActionImpl($request, $iSigner, $credential, $autoRetry, $maxRetryNumber);
162+
if (method_exists($request, 'getDomainParameter') && $request->getDomainParameter()) {
163+
return http_build_query($request->getDomainParameter());
164+
}
165+
return $request->getContent();
101166
}
102-
103-
private function prepareRequest($request)
167+
168+
/**
169+
* 同时发送多个请求
170+
*
171+
* @param array $requests
172+
* @param callable|null $fulfilled
173+
* @param callable|null $rejected
174+
* @param int $concurrency
175+
* @param array $args
176+
* @return mixed
177+
*/
178+
public function sendMultiRequests(
179+
array $requests,
180+
callable $fulfilled = null,
181+
callable $rejected = null,
182+
$concurrency = 5,
183+
array $args = []
184+
)
104185
{
105-
if (null == $request->getRegionId()) {
106-
$request->setRegionId($this->iClientProfile->getRegionId());
107-
}
108-
if (null == $request->getAcceptFormat()) {
109-
$request->setAcceptFormat($this->iClientProfile->getFormat());
110-
}
111-
if (null == $request->getMethod()) {
112-
$request->setMethod("GET");
113-
}
114-
return $request;
186+
$pool = new \GuzzleHttp\Pool($this, $requests, [
187+
'fulfilled' => function (ResponseInterface $response, $index) use ($fulfilled, $requests, $args) {
188+
$respObject = self::parseAcsResponse($response);
189+
if (false == self::isSuccess($response)) {
190+
$this->buildApiException($respObject, $response->getStatusCode());
191+
}
192+
$fulfilled && call_user_func($fulfilled, $respObject, $response, $index, $args);
193+
},
194+
'rejected' => function ($reason, $index) use ($rejected, $args) {
195+
$rejected && call_user_func($rejected, $reason, $index, $args);
196+
},
197+
'concurrency' => $concurrency,
198+
]);
199+
200+
return $pool->promise()->wait();
115201
}
116-
117-
202+
203+
/**
204+
* @param $respObject
205+
* @param $httpStatus
206+
* @throws Exception
207+
* @throws ServerException|\Exception
208+
*/
118209
private function buildApiException($respObject, $httpStatus)
119210
{
120-
throw new ServerException($respObject->Message, $respObject->Code, $httpStatus, $respObject->RequestId);
211+
if (is_object($respObject) && isset($respObject->RequestId)) {
212+
throw new ServerException($respObject->Message, $respObject->Code, $httpStatus, $respObject->RequestId);
213+
} elseif (is_string($respObject)) {
214+
throw new ServerException($respObject, -1, $httpStatus, 0);
215+
} else {
216+
throw new Exception("Invalid response object: " . gettype($respObject));
217+
}
121218
}
122-
123-
private function parseAcsResponse($body, $format)
219+
220+
/**
221+
* @param ResponseInterface $response
222+
* @return mixed|SimpleXMLElement|string
223+
*/
224+
public static function parseAcsResponse(ResponseInterface $response)
124225
{
125-
if ("JSON" == $format) {
126-
$respObject = json_decode($body);
127-
} elseif ("XML" == $format) {
128-
$respObject = @simplexml_load_string($body);
129-
} elseif ("RAW" == $format) {
130-
$respObject = $body;
226+
$contentType = $response->getHeaderLine('Content-Type');
227+
$body = $response->getBody()->getContents();
228+
229+
if (strpos($contentType, 'json') !== false) {
230+
return json_decode($body);
231+
} elseif (strpos($contentType, 'xml') !== false) {
232+
return @simplexml_load_string($body);
233+
} else {
234+
return $body;
131235
}
132-
return $respObject;
133236
}
237+
134238
}

tests/EcsTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
/**
3+
* Ecs test case
4+
*
5+
* User: eagle
6+
* Date: 06/03/2018
7+
* Time: 15:05
8+
*/
9+
10+
class EcsTest extends TestCase
11+
{
12+
13+
public function testDescribeInstances()
14+
{
15+
$request = new Ecs\Request\V20140526\DescribeInstancesRequest();
16+
$request->setRegionId('cn-shanghai');
17+
$response = $this->acsClient->getAcsResponse($request);
18+
$this->assertObjectHasAttribute( 'Instances', $response);
19+
$this->assertInternalType( 'object', $response->Instances);
20+
21+
$this->assertObjectHasAttribute( 'Instance', $response->Instances);
22+
$this->assertInternalType('array', $response->Instances->Instance);
23+
}
24+
}

tests/TestCase.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,28 @@
88

99
class TestCase extends PHPUnit_Framework_TestCase
1010
{
11+
protected $profile;
12+
/** @var \DefaultAcsClient */
13+
protected $acsClient;
14+
15+
public static function setUpBeforeClass()
16+
{
17+
if (!isset($_SERVER['DEFAULT_REGION_ID']) || !isset($_SERVER['ACCESS_KEY_ID']) || !isset($_SERVER['ACCESS_SECRET'])) {
18+
self::markTestSkipped(
19+
'Environment variables REGION_ID and/or ACCESS_KEY_ID and/or ACCESS_SECRET are missing'
20+
);
21+
}
22+
}
23+
24+
protected function setUp()
25+
{
26+
$this->profile = \DefaultProfile::getProfile(
27+
$_SERVER['DEFAULT_REGION_ID'],
28+
$_SERVER['ACCESS_KEY_ID'],
29+
$_SERVER['ACCESS_SECRET']
30+
);
31+
32+
$this->acsClient = new \DefaultAcsClient($this->profile);
33+
}
1134

1235
}

0 commit comments

Comments
 (0)