Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 117a1f6

Browse files
[HttpClient] add ResponseInterface::toArray()
1 parent d4326b2 commit 117a1f6

File tree

6 files changed

+101
-19
lines changed

6 files changed

+101
-19
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"symfony/polyfill-intl-idn": "^1.10",
3535
"symfony/polyfill-mbstring": "~1.0",
3636
"symfony/polyfill-php72": "~1.5",
37-
"symfony/polyfill-php73": "^1.8"
37+
"symfony/polyfill-php73": "^1.11"
3838
},
3939
"replace": {
4040
"symfony/asset": "self.version",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpClient\Exception;
13+
14+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
15+
16+
/**
17+
* Thrown by responses' toArray() method when their content cannot be JSON-decoded.
18+
*
19+
* @author Nicolas Grekas <[email protected]>
20+
*
21+
* @internal
22+
*/
23+
final class JsonException extends \JsonException implements TransportExceptionInterface
24+
{
25+
}

src/Symfony/Component/HttpClient/Response/ResponseTrait.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\HttpClient\Chunk\ErrorChunk;
1616
use Symfony\Component\HttpClient\Chunk\LastChunk;
1717
use Symfony\Component\HttpClient\Exception\ClientException;
18+
use Symfony\Component\HttpClient\Exception\JsonException;
1819
use Symfony\Component\HttpClient\Exception\RedirectionException;
1920
use Symfony\Component\HttpClient\Exception\ServerException;
2021
use Symfony\Component\HttpClient\Exception\TransportException;
@@ -52,6 +53,7 @@ trait ResponseTrait
5253
private $timeout;
5354
private $finalInfo;
5455
private $offset = 0;
56+
private $jsonData;
5557

5658
/**
5759
* {@inheritdoc}
@@ -121,6 +123,47 @@ public function getContent(bool $throw = true): string
121123
return stream_get_contents($this->content);
122124
}
123125

126+
/**
127+
* {@inheritdoc}
128+
*/
129+
public function toArray(bool $throw = true): array
130+
{
131+
if ('' === $content = $this->getContent($throw)) {
132+
throw new TransportException('Response body is empty.');
133+
}
134+
135+
if (null !== $this->jsonData) {
136+
return $this->jsonData;
137+
}
138+
139+
$contentType = $this->headers['content-type'][0] ?? 'application/json';
140+
141+
if (!preg_match('/\bjson\b/i', $contentType)) {
142+
throw new JsonException(sprintf('Response content-type is "%s" while a JSON-compatible one was expected.', $contentType));
143+
}
144+
145+
try {
146+
$content = json_decode($content, true, 512, JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? JSON_THROW_ON_ERROR : 0));
147+
} catch (\JsonException $e) {
148+
throw new JsonException($e->getMessage(), $e->getCode());
149+
}
150+
151+
if (\PHP_VERSION_ID < 70300 && JSON_ERROR_NONE !== json_last_error()) {
152+
throw new JsonException(json_last_error_msg(), json_last_error());
153+
}
154+
155+
if (!\is_array($content)) {
156+
throw new JsonException(sprintf('Response returned %s while an array was expected.', \gettype($content)));
157+
}
158+
159+
if (null !== $this->content) {
160+
// Option "buffer" is true
161+
return $this->jsonData = $content;
162+
}
163+
164+
return $content;
165+
}
166+
124167
/**
125168
* Closes the response and all its network handles.
126169
*/

src/Symfony/Component/HttpClient/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
},
2121
"require": {
2222
"php": "^7.1.3",
23-
"symfony/contracts": "^1.1"
23+
"symfony/contracts": "^1.1",
24+
"symfony/polyfill-php73": "^1.11"
2425
},
2526
"require-dev": {
2627
"nyholm/psr7": "^1.0",

src/Symfony/Contracts/HttpClient/ResponseInterface.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ public function getHeaders(bool $throw = true): array;
5959
*/
6060
public function getContent(bool $throw = true): string;
6161

62+
/**
63+
* Gets the response body decoded as array, typically from a JSON payload.
64+
*
65+
* @param bool $throw Whether an exception should be thrown on 3/4/5xx status codes
66+
*
67+
* @throws TransportExceptionInterface When the body cannot be decoded or when a network error occurs
68+
* @throws RedirectionExceptionInterface On a 3xx when $throw is true and the "max_redirects" option has been reached
69+
* @throws ClientExceptionInterface On a 4xx when $throw is true
70+
* @throws ServerExceptionInterface On a 5xx when $throw is true
71+
*/
72+
public function toArray(bool $throw = true): array;
73+
6274
/**
6375
* Returns info coming from the transport layer.
6476
*

src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public function testGetRequest()
5858
$this->assertSame(['application/json'], $headers['content-type']);
5959

6060
$body = json_decode($response->getContent(), true);
61+
$this->assertSame($body, $response->toArray());
6162

6263
$this->assertSame('HTTP/1.1', $body['SERVER_PROTOCOL']);
6364
$this->assertSame('/', $body['REQUEST_URI']);
@@ -79,7 +80,7 @@ public function testNonBufferedGetRequest()
7980
'headers' => ['Foo' => 'baR'],
8081
]);
8182

82-
$body = json_decode($response->getContent(), true);
83+
$body = $response->toArray();
8384
$this->assertSame('baR', $body['HTTP_FOO']);
8485

8586
$this->expectException(TransportExceptionInterface::class);
@@ -106,7 +107,7 @@ public function testHttpVersion()
106107
$this->assertSame(200, $response->getStatusCode());
107108
$this->assertSame('HTTP/1.0 200 OK', $response->getInfo('raw_headers')[0]);
108109

109-
$body = json_decode($response->getContent(), true);
110+
$body = $response->toArray();
110111

111112
$this->assertSame('HTTP/1.0', $body['SERVER_PROTOCOL']);
112113
$this->assertSame('GET', $body['REQUEST_METHOD']);
@@ -203,7 +204,7 @@ public function testInlineAuth()
203204
$client = $this->getHttpClient();
204205
$response = $client->request('GET', 'http://foo:bar%3Dbar@localhost:8057');
205206

206-
$body = json_decode($response->getContent(), true);
207+
$body = $response->toArray();
207208

208209
$this->assertSame('foo', $body['PHP_AUTH_USER']);
209210
$this->assertSame('bar=bar', $body['PHP_AUTH_PW']);
@@ -219,7 +220,7 @@ public function testRedirects()
219220
},
220221
]);
221222

222-
$body = json_decode($response->getContent(), true);
223+
$body = $response->toArray();
223224
$this->assertSame('GET', $body['REQUEST_METHOD']);
224225
$this->assertSame('Basic Zm9vOmJhcg==', $body['HTTP_AUTHORIZATION']);
225226
$this->assertSame('http://localhost:8057/', $response->getInfo('url'));
@@ -250,7 +251,8 @@ public function testRelativeRedirects()
250251
$client = $this->getHttpClient();
251252
$response = $client->request('GET', 'http://localhost:8057/302/relative');
252253

253-
$body = json_decode($response->getContent(), true);
254+
$body = $response->toArray();
255+
254256
$this->assertSame('/', $body['REQUEST_URI']);
255257
$this->assertNull($response->getInfo('redirect_url'));
256258

@@ -279,7 +281,7 @@ public function testRedirect307()
279281
'body' => 'foo=bar',
280282
]);
281283

282-
$body = json_decode($response->getContent(), true);
284+
$body = $response->toArray();
283285

284286
$this->assertSame(['foo' => 'bar', 'REQUEST_METHOD' => 'POST'], $body);
285287
}
@@ -388,7 +390,7 @@ public function testOnProgress()
388390
'on_progress' => function (...$state) use (&$steps) { $steps[] = $state; },
389391
]);
390392

391-
$body = json_decode($response->getContent(), true);
393+
$body = $response->toArray();
392394

393395
$this->assertSame(['foo' => '0123456789', 'REQUEST_METHOD' => 'POST'], $body);
394396
$this->assertSame([0, 0], \array_slice($steps[0], 0, 2));
@@ -405,7 +407,7 @@ public function testPostArray()
405407
'body' => ['foo' => 'bar'],
406408
]);
407409

408-
$this->assertSame(['foo' => 'bar', 'REQUEST_METHOD' => 'POST'], json_decode($response->getContent(), true));
410+
$this->assertSame(['foo' => 'bar', 'REQUEST_METHOD' => 'POST'], $response->toArray());
409411
}
410412

411413
public function testPostResource()
@@ -420,7 +422,7 @@ public function testPostResource()
420422
'body' => $h,
421423
]);
422424

423-
$body = json_decode($response->getContent(), true);
425+
$body = $response->toArray();
424426

425427
$this->assertSame(['foo' => '0123456789', 'REQUEST_METHOD' => 'POST'], $body);
426428
}
@@ -438,7 +440,7 @@ public function testPostCallback()
438440
},
439441
]);
440442

441-
$this->assertSame(['foo' => '0123456789', 'REQUEST_METHOD' => 'POST'], json_decode($response->getContent(), true));
443+
$this->assertSame(['foo' => '0123456789', 'REQUEST_METHOD' => 'POST'], $response->toArray());
442444
}
443445

444446
public function testOnProgressCancel()
@@ -581,15 +583,15 @@ public function testProxy()
581583
'proxy' => 'http://localhost:8057',
582584
]);
583585

584-
$body = json_decode($response->getContent(), true);
586+
$body = $response->toArray();
585587
$this->assertSame('localhost:8057', $body['HTTP_HOST']);
586588
$this->assertRegexp('#^http://(localhost|127\.0\.0\.1):8057/$#', $body['REQUEST_URI']);
587589

588590
$response = $client->request('GET', 'http://localhost:8057/', [
589591
'proxy' => 'http://foo:b%3Dar@localhost:8057',
590592
]);
591593

592-
$body = json_decode($response->getContent(), true);
594+
$body = $response->toArray();
593595
$this->assertSame('Basic Zm9vOmI9YXI=', $body['HTTP_PROXY_AUTHORIZATION']);
594596
}
595597

@@ -603,7 +605,7 @@ public function testNoProxy()
603605
'proxy' => 'http://localhost:8057',
604606
]);
605607

606-
$body = json_decode($response->getContent(), true);
608+
$body = $response->toArray();
607609

608610
$this->assertSame('HTTP/1.1', $body['SERVER_PROTOCOL']);
609611
$this->assertSame('/', $body['REQUEST_URI']);
@@ -629,7 +631,7 @@ public function testAutoEncodingRequest()
629631
$this->assertSame(['Accept-Encoding'], $headers['vary']);
630632
$this->assertContains('gzip', $headers['content-encoding'][0]);
631633

632-
$body = json_decode($response->getContent(), true);
634+
$body = $response->toArray();
633635

634636
$this->assertContains('gzip', $body['HTTP_ACCEPT_ENCODING']);
635637
}
@@ -652,7 +654,7 @@ public function testQuery()
652654
'query' => ['b' => 'b'],
653655
]);
654656

655-
$body = json_decode($response->getContent(), true);
657+
$body = $response->toArray();
656658
$this->assertSame('GET', $body['REQUEST_METHOD']);
657659
$this->assertSame('/?a=a&b=b', $body['REQUEST_URI']);
658660
}
@@ -673,10 +675,9 @@ public function testUserlandEncodingRequest()
673675
$this->assertContains('gzip', $headers['content-encoding'][0]);
674676

675677
$body = $response->getContent();
676-
677678
$this->assertSame("\x1F", $body[0]);
678-
$body = json_decode(gzdecode($body), true);
679679

680+
$body = json_decode(gzdecode($body), true);
680681
$this->assertSame('gzip', $body['HTTP_ACCEPT_ENCODING']);
681682
}
682683

0 commit comments

Comments
 (0)