Skip to content

Commit

Permalink
[HttpClient][DX] Add URL context to JsonException messages
Browse files Browse the repository at this point in the history
  • Loading branch information
GromNaN authored and nicolas-grekas committed Feb 25, 2020
1 parent 88b89c9 commit 0653917
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/Symfony/Component/HttpClient/Response/ResponseTrait.php
Expand Up @@ -147,21 +147,21 @@ public function toArray(bool $throw = true): array
$contentType = $this->headers['content-type'][0] ?? 'application/json';

if (!preg_match('/\bjson\b/i', $contentType)) {
throw new JsonException(sprintf('Response content-type is "%s" while a JSON-compatible one was expected.', $contentType));
throw new JsonException(sprintf('Response content-type is "%s" while a JSON-compatible one was expected for "%s".', $contentType, $this->getInfo('url')));
}

try {
$content = json_decode($content, true, 512, JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? JSON_THROW_ON_ERROR : 0));
} catch (\JsonException $e) {
throw new JsonException($e->getMessage(), $e->getCode());
throw new JsonException(sprintf('%s for "%s".', $e->getMessage(), $this->getInfo('url')), $e->getCode());
}

if (\PHP_VERSION_ID < 70300 && JSON_ERROR_NONE !== json_last_error()) {
throw new JsonException(json_last_error_msg(), json_last_error());
throw new JsonException(sprintf('%s for "%s".', json_last_error_msg(), $this->getInfo('url')), json_last_error());
}

if (!\is_array($content)) {
throw new JsonException(sprintf('JSON content was expected to decode to an array, %s returned.', \gettype($content)));
throw new JsonException(sprintf('JSON content was expected to decode to an array, %s returned for "%s".', \gettype($content), $this->getInfo('url')));
}

if (null !== $this->content) {
Expand Down
@@ -0,0 +1,68 @@
<?php

namespace Symfony\Component\HttpClient\Tests\Response;

use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpClient\Exception\JsonException;
use Symfony\Component\HttpClient\Response\MockResponse;

/**
* Test methods from Symfony\Component\HttpClient\Response\ResponseTrait.
*/
class MockResponseTest extends TestCase
{
public function testToArray()
{
$data = ['color' => 'orange', 'size' => 42];
$response = new MockResponse(json_encode($data));
$response = MockResponse::fromRequest('GET', 'https://example.com/file.json', [], $response);

$this->assertSame($data, $response->toArray());
}

/**
* @dataProvider toArrayErrors
*/
public function testToArrayError($content, $responseHeaders, $message)
{
$this->expectException(JsonException::class);
$this->expectExceptionMessage($message);

$response = new MockResponse($content, ['response_headers' => $responseHeaders]);
$response = MockResponse::fromRequest('GET', 'https://example.com/file.json', [], $response);
$response->toArray();
}

public function toArrayErrors()
{
yield [
'content' => '{}',
'responseHeaders' => ['content-type' => 'plain/text'],
'message' => 'Response content-type is "plain/text" while a JSON-compatible one was expected for "https://example.com/file.json".',
];

yield [
'content' => 'not json',
'responseHeaders' => [],
'message' => 'Syntax error for "https://example.com/file.json".',
];

yield [
'content' => '[1,2}',
'responseHeaders' => [],
'message' => 'State mismatch (invalid or malformed JSON) for "https://example.com/file.json".',
];

yield [
'content' => '"not an array"',
'responseHeaders' => [],
'message' => 'JSON content was expected to decode to an array, string returned for "https://example.com/file.json".',
];

yield [
'content' => '8',
'responseHeaders' => [],
'message' => 'JSON content was expected to decode to an array, integer returned for "https://example.com/file.json".',
];
}
}

0 comments on commit 0653917

Please sign in to comment.