Skip to content

Commit 15b1370

Browse files
feature #49798 [HttpClient] Add ServerSentEvent::getArrayData() to get the SSE's data decoded as an array directly (fancyweb)
This PR was merged into the 6.3 branch. Discussion ---------- [HttpClient] Add ServerSentEvent::getArrayData() to get the SSE's data decoded as an array directly | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Although the data field in SSEs can be "anything", it's really common that it's a JSON payload. Just like we have a shortcut in responses (`ResponseInterface::toArray()`), I think it's worth having a shortcut in `ServerSentEvent` to avoid writing boilerplate code again and again 😅 Commits ------- cdbf939210 [HttpClient] Add ServerSentEvent::getArrayData() to get the SSE's data decoded as an array directly
2 parents f312fd7 + 3cc797a commit 15b1370

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
---
66

77
* Add `UriTemplateHttpClient` to use URI templates as specified in the RFC 6570
8+
* Add `ServerSentEvent::getArrayData()` to get the Server-Sent Event's data decoded as an array when it's a JSON payload
89

910
6.2
1011
---

Chunk/ServerSentEvent.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\HttpClient\Chunk;
1313

14+
use Symfony\Component\HttpClient\Exception\JsonException;
1415
use Symfony\Contracts\HttpClient\ChunkInterface;
1516

1617
/**
@@ -23,6 +24,7 @@ final class ServerSentEvent extends DataChunk implements ChunkInterface
2324
private string $id = '';
2425
private string $type = 'message';
2526
private float $retry = 0;
27+
private ?array $jsonData = null;
2628

2729
public function __construct(string $content)
2830
{
@@ -76,4 +78,30 @@ public function getRetry(): float
7678
{
7779
return $this->retry;
7880
}
81+
82+
/**
83+
* Gets the SSE data decoded as an array when it's a JSON payload.
84+
*/
85+
public function getArrayData(): array
86+
{
87+
if (null !== $this->jsonData) {
88+
return $this->jsonData;
89+
}
90+
91+
if ('' === $this->data) {
92+
throw new JsonException(sprintf('Server-Sent Event%s data is empty.', '' !== $this->id ? sprintf(' "%s"', $this->id) : ''));
93+
}
94+
95+
try {
96+
$jsonData = json_decode($this->data, true, 512, \JSON_BIGINT_AS_STRING | \JSON_THROW_ON_ERROR);
97+
} catch (\JsonException $e) {
98+
throw new JsonException(sprintf('Decoding Server-Sent Event%s failed: ', '' !== $this->id ? sprintf(' "%s"', $this->id) : '').$e->getMessage(), $e->getCode());
99+
}
100+
101+
if (!\is_array($jsonData)) {
102+
throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned in Server-Sent Event%s.', get_debug_type($jsonData), '' !== $this->id ? sprintf(' "%s"', $this->id) : ''));
103+
}
104+
105+
return $this->jsonData = $jsonData;
106+
}
79107
}

Tests/Chunk/ServerSentEventTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\HttpClient\Chunk\ServerSentEvent;
16+
use Symfony\Component\HttpClient\Exception\JsonException;
1617

1718
/**
1819
* @author Antoine Bluchet <soyuka@gmail.com>
@@ -76,4 +77,45 @@ public function testParseNewLine()
7677
$sse = new ServerSentEvent($rawData);
7778
$this->assertSame("<tag>\n\n <foo />\n\n\n</tag>", $sse->getData());
7879
}
80+
81+
public function testGetArrayData()
82+
{
83+
$this->assertSame(['foo' => 'bar'], (new ServerSentEvent(<<<STR
84+
id: 33
85+
data: {"foo": "bar"}
86+
STR
87+
))->getArrayData());
88+
}
89+
90+
public function testGetArrayDataWithNoContent()
91+
{
92+
$this->expectException(JsonException::class);
93+
$this->expectExceptionMessage('Server-Sent Event data is empty.');
94+
95+
(new ServerSentEvent(''))->getArrayData();
96+
}
97+
98+
public function testGetArrayDataWithInvalidJson()
99+
{
100+
$this->expectException(JsonException::class);
101+
$this->expectExceptionMessage('Decoding Server-Sent Event "33" failed: Syntax error');
102+
103+
(new ServerSentEvent(<<<STR
104+
id: 33
105+
data: foobarccc
106+
STR
107+
))->getArrayData();
108+
}
109+
110+
public function testGetArrayDataWithNonArrayJson()
111+
{
112+
$this->expectException(JsonException::class);
113+
$this->expectExceptionMessage('JSON content was expected to decode to an array, "string" returned in Server-Sent Event "33".');
114+
115+
(new ServerSentEvent(<<<STR
116+
id: 33
117+
data: "ccc"
118+
STR
119+
))->getArrayData();
120+
}
79121
}

0 commit comments

Comments
 (0)