'Bar']);
$result = new Result();
$handler = function (RequestInterface $request, array $options) use (&$called, $res, $req) {
$this->assertSame($request, $req);
$called = true;
return $res;
};
$parser = function (CommandInterface $command, ResponseInterface $response) use ($res, $cmd, $result) {
$this->assertSame($res, $response);
$this->assertSame($cmd, $command);
return $result;
};
$errorParser = [$this, 'fail'];
$wrapped = new WrappedHttpHandler($handler, $parser, $errorParser);
$promise = $wrapped($cmd, $req);
$this->assertTrue($called);
$this->assertInstanceOf('GuzzleHttp\Promise\PromiseInterface', $promise);
$this->assertSame($result, $promise->wait());
$this->assertEquals([
'statusCode' => 200,
'effectiveUri' => (string) $req->getUri(),
'headers' => ['foo' => 'Bar'],
'transferStats' => [],
], $result['@metadata']);
}
public function testEnsuresErrorHasExceptionKey()
{
$this->expectExceptionMessage("The HTTP handler was rejected without an \"exception\" key value pair.");
$this->expectException(\RuntimeException::class);
$cmd = new Command('foo');
$req = new Request('GET', 'http://foo.com');
$handler = function () { return new RejectedPromise([]); };
$parser = $errorParser = [$this, 'fail'];
$wrapped = new WrappedHttpHandler($handler, $parser, $errorParser);
$wrapped($cmd, $req)->wait();
}
public function testCanRejectWithoutResponse()
{
$e = new \Exception('a');
$cmd = new Command('foo');
$req = new Request('GET', 'http://foo.com');
$handler = function () use ($e) {
return new RejectedPromise(['exception' => $e]);
};
$parser = $errorParser = [$this, 'fail'];
$wrapped = new WrappedHttpHandler($handler, $parser, $errorParser);
try {
$wrapped($cmd, $req)->wait();
$this->fail();
} catch (AwsException $e) {
$this->assertSame($req, $e->getRequest());
$this->assertSame($cmd, $e->getCommand());
$this->assertNull($e->getResponse());
$this->assertNull($e->getResult());
}
}
/**
* @dataProvider responseAndParserProvider
*
* @param Response $res
* @param $errorParser
* @param $expectedCode
* @param $expectedId
* @param $expectedArray
*/
public function testCanRejectWithAndParseResponse(
Response $res,
Service $service,
$errorParser,
$expectedCode,
$expectedId,
$expectedArray
)
{
$client = $this->generateTestClient($service, []);
$cmd = $client->getCommand('TestOperation', []);
$e = new \Exception('a');
$req = new Request('GET', 'http://foo.com');
$handler = function () use ($e, $req, $res) {
return new RejectedPromise(['exception' => $e, 'response' => $res]);
};
$parser = [$this, 'fail'];
$wrapped = new WrappedHttpHandler($handler, $parser, $errorParser);
try {
$wrapped($cmd, $req)->wait();
$this->fail();
} catch (AwsException $e) {
$this->assertSame($cmd, $e->getCommand());
$this->assertSame($res, $e->getResponse());
$this->assertSame($req, $e->getRequest());
$this->assertNull($e->getResult());
$this->assertEquals($expectedCode, $e->getAwsErrorCode());
$this->assertEquals($expectedId, $e->getAwsRequestId());
$this->assertEquals($expectedArray, $e->toArray());
}
}
public function responseAndParserProvider()
{
$services = [
'ec2' => $this->generateTestService('ec2'),
'json' => $this->generateTestService('json'),
'query' => $this->generateTestService('query'),
'rest-json' => $this->generateTestService('rest-json'),
'rest-xml' => $this->generateTestService('rest-xml'),
];
return [
[
new Response(
400,
['X-Amzn-RequestId' => '123'],
json_encode(['__type' => 'foo#bar'])
),
$services['json'],
new JsonRpcErrorParser($services['json']),
'bar',
'123',
[],
],
[
new Response(
400,
[
'X-Amzn-RequestId' => '123',
],
json_encode(['message' => 'sorry!'])
),
$services['rest-json'],
new RestJsonErrorParser($services['rest-json']),
null,
'123',
[],
],
[
new Response(
400,
[],
'InternalError
656c76696e6727732072657175657374'
),
$services['rest-xml'],
new XmlErrorParser($services['rest-xml']),
'InternalError',
'656c76696e6727732072657175657374',
[],
],
[
new Response(
400,
['X-Amzn-RequestId' => '123'],
openssl_random_pseudo_bytes(1024)
),
$services['query'],
new XmlErrorParser($services['query']),
null,
null,
[],
],
// Rest-json with modeled exception from header error type
[
new Response(
400,
[
'X-Amzn-RequestId' => '123',
'X-Amzn-ErrorType' => 'TestException'
],
json_encode([
'TestString' => 'foo-string',
'TestInt' => 456,
'NotModeled' => 'bar'
])
),
$services['rest-json'],
new RestJsonErrorParser($services['rest-json']),
'TestException',
'123',
[
'TestString' => 'foo-string',
'TestInt' => 456,
'TestHeaderMember' => '',
'TestHeaders' => [],
'TestStatus' => 400
],
],
// Rest-json with modeled exception from body error code
[
new Response(
400,
[
'X-Amzn-RequestId' => '123'
],
json_encode([
'TestString' => 'foo-string',
'TestInt' => 456,
'NotModeled' => 'bar',
'code' => 'TestException'
])
),
$services['rest-json'],
new RestJsonErrorParser($services['rest-json']),
'TestException',
'123',
[
'TestString' => 'foo-string',
'TestInt' => 456,
'TestHeaderMember' => '',
'TestHeaders' => [],
'TestStatus' => 400
],
],
// Ec2 with modeled exception
[
new Response(
400,
[],
'' . "\n" .
'' .
' ' .
' ' .
' TestException
' .
' Error Message' .
' SomeString' .
' 456' .
' ' .
' ' .
' xyz' .
''
),
$services['ec2'],
new XmlErrorParser($services['ec2']),
'TestException',
'xyz',
[
'TestString' => 'SomeString',
'TestInt' => 456,
'TestHeaderMember' => '',
'TestHeaders' => [],
'TestStatus' => 400,
],
],
// Query with modeled exception
[
new Response(
400,
[],
'' .
' ' .
' ErrorType' .
' TestException
' .
' Error Message' .
' SomeString' .
' 456' .
' ' .
' xyz' .
''
),
$services['query'],
new XmlErrorParser($services['query']),
'TestException',
'xyz',
[
'TestString' => 'SomeString',
'TestInt' => 456,
'TestHeaderMember' => '',
'TestHeaders' => [],
'TestStatus' => 400,
],
],
// Rest-xml with modeled exception
[
new Response(
400,
[],
'' .
' ' .
' ErrorType' .
' TestException
' .
' Error Message' .
' SomeString' .
' 456' .
' ' .
' xyz' .
''
),
$services['rest-xml'],
new XmlErrorParser($services['rest-xml']),
'TestException',
'xyz',
[
'TestString' => 'SomeString',
'TestInt' => 456,
'TestHeaderMember' => '',
'TestHeaders' => [],
'TestStatus' => 400,
],
],
];
}
public function testCanRejectWithException()
{
$e = new \Exception('a');
$cmd = new Command('foo');
$req = new Request('GET', 'http://foo.com');
$handler = function () use ($e) { throw $e; };
$parser = [$this, 'fail'];
$errorParser = [$this, 'fail'];
$wrapped = new WrappedHttpHandler($handler, $parser, $errorParser);
try {
$wrapped($cmd, $req)->wait();
$this->fail();
} catch (\Exception $e2) {
$this->assertSame($e, $e2);
}
}
public function testDoesNotPassOnTransferStatsCallbackToHandlerByDefault()
{
$handler = function ($request, array $options) {
$this->assertArrayNotHasKey('http_stats_receiver', $options);
return new Response;
};
$parser = function () { return new Result; };
$wrapped = new WrappedHttpHandler($handler, $parser, [$this, 'fail']);
$wrapped(new Command('a'), new Request('GET', 'http://foo.com'))
->wait();
}
public function testPassesOnTransferStatsCallbackToHandlerWhenRequested()
{
$handler = function ($request, array $options) {
$this->assertArrayHasKey('http_stats_receiver', $options);
$this->assertIsCallable($options['http_stats_receiver']);
return new Response;
};
$parser = function () { return new Result; };
$wrapped = new WrappedHttpHandler(
$handler,
$parser,
[$this, 'fail'],
AwsException::class,
$collectStats = true
);
$wrapped(new Command('a'), new Request('GET', 'http://foo.com'))
->wait();
}
}