Skip to content

Commit 6d018e0

Browse files
authored
Refactor HttpExceptionTrait (#345)
* Refactor HttpExceptionTrait * Fixed tests * Fallback to XML
1 parent f0368a5 commit 6d018e0

File tree

3 files changed

+65
-44
lines changed

3 files changed

+65
-44
lines changed

src/Exception/Http/HttpExceptionTrait.php

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
/**
88
* @author Nicolas Grekas <[email protected]>
9+
* @author Tobias Nyholm <[email protected]>
10+
* @author Jérémy Derussé <[email protected]>
911
*
1012
* @internal
1113
*/
@@ -66,41 +68,28 @@ public function __construct(ResponseInterface $response)
6668
}
6769
}
6870

69-
// Try to guess a better error message using common API error formats
70-
// The MIME type isn't explicitly checked because some formats inherit from others
71-
// Ex: JSON:API follows RFC 7807 semantics, Hydra can be used in any JSON-LD-compatible format
72-
if ($isJson && $body = json_decode($response->getContent(false), true)) {
73-
if (isset($body['__type'])) {
74-
$parts = explode('#', $body['__type'], 2);
75-
$this->awsCode = $parts[1] ?? $parts[0];
76-
$message .= "\n\n" . $body['__type'] . "\n\n";
77-
}
78-
79-
if (isset($body['hydra:title']) || isset($body['hydra:description'])) {
80-
// see http://www.hydra-cg.com/spec/latest/core/#description-of-http-status-codes-and-errors
81-
$separator = isset($body['hydra:title'], $body['hydra:description']) ? "\n\n" : '';
82-
$message = ($body['hydra:title'] ?? '') . $separator . ($body['hydra:description'] ?? '');
83-
} elseif (isset($body['title']) || isset($body['detail'])) {
84-
// see RFC 7807 and https://jsonapi.org/format/#error-objects
85-
$separator = isset($body['title'], $body['detail']) ? "\n\n" : '';
86-
$message = ($body['title'] ?? '') . $separator . ($body['detail'] ?? '');
87-
} elseif (isset($body['message'])) {
88-
$this->awsMessage = $body['message'];
89-
$message .= "\n\n" . $body['message'] . "\n\n";
90-
} elseif (isset($body['Message'])) {
91-
$this->awsMessage = $body['Message'];
92-
$message .= "\n\n" . $body['Message'] . "\n\n";
93-
}
71+
$content = $response->getContent(false);
72+
if ($isJson && $body = json_decode($content, true)) {
73+
$this->parseJson($body);
9474
} else {
9575
try {
96-
$body = $response->getContent(false);
97-
$xml = new \SimpleXMLElement($body);
98-
$message .= $this->parseXml($xml);
76+
$xml = new \SimpleXMLElement($content);
77+
$this->parseXml($xml);
9978
} catch (\Throwable $e) {
10079
// Not XML ¯\_(ツ)_/¯
10180
}
10281
}
10382

83+
$message .= <<<TEXT
84+
85+
86+
Code: $this->awsCode
87+
Message: $this->awsMessage
88+
Type: $this->awsType
89+
Detail: $this->awsDetail
90+
91+
TEXT;
92+
10493
parent::__construct($message, $code);
10594
}
10695

@@ -129,7 +118,7 @@ public function getAwsDetail(): ?string
129118
return $this->awsDetail;
130119
}
131120

132-
private function parseXml(\SimpleXMLElement $xml): string
121+
private function parseXml(\SimpleXMLElement $xml): void
133122
{
134123
if (0 < $xml->Error->count()) {
135124
$this->awsType = $xml->Error->Type->__toString();
@@ -140,18 +129,23 @@ private function parseXml(\SimpleXMLElement $xml): string
140129
$this->awsType = $this->awsDetail = '';
141130
$this->awsCode = $xml->Code->__toString();
142131
$this->awsMessage = $xml->Message->__toString();
143-
} else {
144-
return '';
145132
}
133+
}
146134

147-
return <<<TEXT
148-
149-
150-
Code: $this->awsCode
151-
Message: $this->awsMessage
152-
Type: $this->awsType
153-
Detail: $this->awsDetail
135+
private function parseJson($body): void
136+
{
137+
if (isset($body['message'])) {
138+
$this->awsMessage = $body['message'];
139+
} elseif (isset($body['Message'])) {
140+
$this->awsMessage = $body['Message'];
141+
}
154142

155-
TEXT;
143+
if (isset($body['Type'])) {
144+
$this->awsType = $body['Type'];
145+
} elseif (isset($body['__type'])) {
146+
$parts = explode('#', $body['__type'], 2);
147+
$this->awsCode = $parts[1] ?? $parts[0];
148+
$this->awsType = $body['__type'];
149+
}
156150
}
157151
}

tests/Unit/Exception/Http/ClientExceptionTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,35 @@ public function testDynamoDbError()
4949
self::assertSame('ResourceNotFoundException', $exception->getAwsCode());
5050
self::assertSame('Requested resource not found: Table: tablename not found', $exception->getAwsMessage());
5151
}
52+
53+
public function testCloudFormationXmlError()
54+
{
55+
$content = '<ErrorResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
56+
<Error>
57+
<Type>Sender</Type>
58+
<Code>ValidationError</Code>
59+
<Message>Stack [foo-dev] does not exist</Message>
60+
</Error>
61+
<RequestId>f1479c09-9fff-498a-89e5-b69d211fa206</RequestId>
62+
</ErrorResponse>
63+
';
64+
$response = new SimpleMockedResponse($content, ['content-type' => 'text/xml'], 400);
65+
$exception = new ClientException($response);
66+
67+
self::assertSame(400, $exception->getCode());
68+
self::assertSame('Sender', $exception->getAwsType());
69+
self::assertSame('ValidationError', $exception->getAwsCode());
70+
self::assertSame('Stack [foo-dev] does not exist', $exception->getAwsMessage());
71+
}
72+
73+
public function testLambdaJsonError()
74+
{
75+
$content = '{"Type":"User","message":"Invalid Layer name: arn:aws:lambda:eu-central-2:12345:layer:foobar"}';
76+
$response = new SimpleMockedResponse($content, ['content-type' => 'application/json'], 400);
77+
$exception = new ClientException($response);
78+
79+
self::assertSame(400, $exception->getCode());
80+
self::assertSame('User', $exception->getAwsType());
81+
self::assertSame('Invalid Layer name: arn:aws:lambda:eu-central-2:12345:layer:foobar', $exception->getAwsMessage());
82+
}
5283
}

tests/Unit/Test/ResultMockFactoryTest.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,7 @@ public function testCreateFailling()
7575

7676
$this->expectException(ClientException::class);
7777
$this->expectExceptionCode(400);
78-
$this->expectExceptionMessage('HTTP 400 returned for "http://localhost/".
79-
80-
Boom
81-
82-
');
78+
$this->expectExceptionMessageRegExp('@HTTP 400 returned for "http://localhost/".*Boom@sm');
8379

8480
$result->resolve();
8581
}

0 commit comments

Comments
 (0)