Skip to content

Commit 2ce9aae

Browse files
authored
Merge pull request #111 from swisnl/bugfix/handle-empty-response
fix: improve responseHasBody check for responses with an unknown size
2 parents 23b4139 + 428734e commit 2ce9aae

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

src/Parsers/ResponseParser.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,25 @@ public function parse(ResponseInterface $response): DocumentInterface
4646

4747
private function responseHasBody(ResponseInterface $response): bool
4848
{
49-
return (bool) $response->getBody()->getSize();
49+
$body = $response->getBody();
50+
$size = $body->getSize();
51+
52+
if ($size === 0) {
53+
return false;
54+
}
55+
if (is_int($size) && $size > 0) {
56+
return true;
57+
}
58+
59+
if ($body->isSeekable()) {
60+
$pos = $body->tell();
61+
$chunk = $body->read(1);
62+
$body->seek($pos);
63+
} else {
64+
$chunk = $body->read(1);
65+
}
66+
67+
return $chunk !== '';
5068
}
5169

5270
private function responseHasSuccessfulStatusCode(ResponseInterface $response): bool

tests/Parsers/ResponseParserTest.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
namespace Swis\JsonApi\Client\Tests\Parsers;
66

7+
use GuzzleHttp\Psr7\PumpStream;
78
use GuzzleHttp\Psr7\Response;
89
use PHPUnit\Framework\TestCase;
10+
use Psr\Http\Message\StreamInterface;
911
use Swis\JsonApi\Client\CollectionDocument;
1012
use Swis\JsonApi\Client\Document;
1113
use Swis\JsonApi\Client\InvalidResponseDocument;
@@ -59,6 +61,95 @@ public function it_parses_a_response_with_an_empty_body()
5961
$this->assertSame($response, $document->getResponse());
6062
}
6163

64+
/**
65+
* @test
66+
*/
67+
public function it_parses_a_response_with_an_empty_body_and_unknown_size()
68+
{
69+
$documentParser = $this->createMock(DocumentParser::class);
70+
$documentParser->expects($this->never())
71+
->method('parse');
72+
73+
$parser = new ResponseParser($documentParser);
74+
75+
$stream = new PumpStream(function () {
76+
return false;
77+
});
78+
79+
$response = new Response(204, [], $stream);
80+
81+
$document = $parser->parse($response);
82+
83+
$this->assertInstanceOf(Document::class, $document);
84+
$this->assertSame($response, $document->getResponse());
85+
}
86+
87+
/**
88+
* @test
89+
*/
90+
public function it_parses_a_response_with_a_body_and_unknown_size()
91+
{
92+
$json = json_encode(['meta' => ['ok' => true]]);
93+
94+
$stream = new PumpStream(function () use ($json) {
95+
static $done = false;
96+
if ($done) {
97+
return false;
98+
}
99+
$done = true;
100+
101+
return $json;
102+
});
103+
104+
$parsedDocument = new Document;
105+
106+
$documentParser = $this->createMock(DocumentParser::class);
107+
$documentParser
108+
->expects($this->once())
109+
->method('parse')
110+
->with($this->isType('string'))
111+
->willReturn($parsedDocument);
112+
113+
$parser = new ResponseParser($documentParser);
114+
115+
$response = new Response(200, [], $stream);
116+
117+
$document = $parser->parse($response);
118+
119+
$this->assertSame($parsedDocument, $document);
120+
$this->assertSame($response, $document->getResponse());
121+
}
122+
123+
/**
124+
* @test
125+
*/
126+
public function it_parses_a_response_with_a_seekable_stream_and_unknown_size()
127+
{
128+
$stream = $this->createMock(StreamInterface::class);
129+
$stream->method('getSize')->willReturn(-1);
130+
$stream->method('isSeekable')->willReturn(true);
131+
$stream->method('tell')->willReturn(0);
132+
$stream->expects($this->once())->method('read')->with(1)->willReturn('x');
133+
$stream->expects($this->once())->method('seek')->with(0);
134+
135+
$parsedDocument = new Document;
136+
137+
$documentParser = $this->createMock(DocumentParser::class);
138+
$documentParser
139+
->expects($this->once())
140+
->method('parse')
141+
->with($this->isType('string'))
142+
->willReturn($parsedDocument);
143+
144+
$parser = new ResponseParser($documentParser);
145+
$response = new Response(200, [], $stream);
146+
147+
$document = $parser->parse($response);
148+
149+
$this->assertSame($parsedDocument, $document);
150+
$this->assertSame($response, $document->getResponse());
151+
}
152+
62153
/**
63154
* @test
64155
*/

0 commit comments

Comments
 (0)