Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit aabd1d4

Browse filesBrowse files
[HttpClient] add ResponseInterface::toArray()
1 parent d4326b2 commit aabd1d4
Copy full SHA for aabd1d4

File tree

6 files changed

+101
-19
lines changed
Filter options

6 files changed

+101
-19
lines changed

‎composer.json

Copy file name to clipboardExpand all lines: composer.json
+1-1Lines 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",
+25Lines 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 <fabien@symfony.com>
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 <p@tchwork.com>
20+
*
21+
* @internal
22+
*/
23+
final class JsonException extends \JsonException implements TransportExceptionInterface
24+
{
25+
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpClient/Response/ResponseTrait.php
+43Lines 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('JSON content was expected to decode to an array, %s returned.', \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

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpClient/composer.json
+2-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Contracts/HttpClient/ResponseInterface.php
+12Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php
+18-17Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.