Skip to content

Commit ec07bab

Browse files
[HttpClient] allow option "buffer" to be a stream resource
1 parent 26ce72f commit ec07bab

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

HttpClient/HttpClientInterface.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ interface HttpClientInterface
4545
// NOT follow except for the initial host name
4646
'http_version' => null, // string - defaults to the best supported version, typically 1.1 or 2.0
4747
'base_uri' => null, // string - the URI to resolve relative URLs, following rules in RFC 3986, section 2
48-
'buffer' => true, // bool - whether the content of the response should be buffered or not
48+
'buffer' => true, // bool|resource|\Closure - whether the content of the response should be buffered or not,
49+
// or a stream resource where the response body should be written,
50+
// or a closure telling if/where the response should be buffered based on its headers
4951
'on_progress' => null, // callable(int $dlNow, int $dlSize, array $info) - throwing any exceptions MUST abort
5052
// the request; it MUST be called on DNS resolution, on arrival of headers and on
5153
// completion; it SHOULD be called on upload/download of data and at least 1/s

HttpClient/Test/HttpClientTestCase.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,70 @@ public function testNonBufferedGetRequest()
8787
$response->getContent();
8888
}
8989

90+
public function testBufferSink()
91+
{
92+
$sink = fopen('php://temp', 'w+');
93+
$client = $this->getHttpClient(__FUNCTION__);
94+
$response = $client->request('GET', 'http://localhost:8057', [
95+
'buffer' => $sink,
96+
'headers' => ['Foo' => 'baR'],
97+
]);
98+
99+
$body = $response->toArray();
100+
$this->assertSame('baR', $body['HTTP_FOO']);
101+
102+
rewind($sink);
103+
$sink = stream_get_contents($sink);
104+
$this->assertSame($sink, $response->getContent());
105+
}
106+
107+
public function testConditionalBuffering()
108+
{
109+
$client = $this->getHttpClient(__FUNCTION__);
110+
$response = $client->request('GET', 'http://localhost:8057');
111+
$firstContent = $response->getContent();
112+
$secondContent = $response->getContent();
113+
114+
$this->assertSame($firstContent, $secondContent);
115+
116+
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => function () { return false; }]);
117+
$response->getContent();
118+
119+
$this->expectException(TransportExceptionInterface::class);
120+
$response->getContent();
121+
}
122+
123+
public function testReentrantBufferCallback()
124+
{
125+
$client = $this->getHttpClient(__FUNCTION__);
126+
127+
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => function () use (&$response) {
128+
$response->cancel();
129+
130+
return true;
131+
}]);
132+
133+
$this->assertSame(200, $response->getStatusCode());
134+
135+
$this->expectException(TransportExceptionInterface::class);
136+
$response->getContent();
137+
}
138+
139+
public function testThrowingBufferCallback()
140+
{
141+
$client = $this->getHttpClient(__FUNCTION__);
142+
143+
$response = $client->request('GET', 'http://localhost:8057', ['buffer' => function () {
144+
throw new \Exception('Boo');
145+
}]);
146+
147+
$this->assertSame(200, $response->getStatusCode());
148+
149+
$this->expectException(TransportExceptionInterface::class);
150+
$this->expectExceptionMessage('Boo');
151+
$response->getContent();
152+
}
153+
90154
public function testUnsupportedOption()
91155
{
92156
$client = $this->getHttpClient(__FUNCTION__);

0 commit comments

Comments
 (0)