2
namespace GuzzleHttp\Tests\Adapter;
4
use GuzzleHttp\Adapter\StreamAdapter;
6
use GuzzleHttp\Event\ErrorEvent;
7
use GuzzleHttp\Message\MessageFactory;
8
use GuzzleHttp\Message\Response;
9
use GuzzleHttp\Stream\Stream;
10
use GuzzleHttp\Tests\Server;
13
* @covers GuzzleHttp\Adapter\StreamAdapter
15
class StreamAdapterTest extends \PHPUnit_Framework_TestCase
17
public function testReturnsResponseForSuccessfulRequest()
21
"HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 2\r\n\r\nhi"
23
$client = new Client([
24
'base_url' => Server::$url,
25
'adapter' => new StreamAdapter(new MessageFactory())
27
$response = $client->get('/', ['headers' => ['Foo' => 'Bar']]);
28
$this->assertEquals(200, $response->getStatusCode());
29
$this->assertEquals('OK', $response->getReasonPhrase());
30
$this->assertEquals('Bar', $response->getHeader('Foo'));
31
$this->assertEquals('2', $response->getHeader('Content-Length'));
32
$this->assertEquals('hi', $response->getBody());
33
$sent = Server::received(true)[0];
34
$this->assertEquals('GET', $sent->getMethod());
35
$this->assertEquals('/', $sent->getResource());
36
$this->assertEquals('127.0.0.1:8125', $sent->getHeader('host'));
37
$this->assertEquals('Bar', $sent->getHeader('foo'));
38
$this->assertTrue($sent->hasHeader('user-agent'));
42
* @expectedException \GuzzleHttp\Exception\RequestException
43
* @expectedExceptionMessage Error creating resource. [url] http://localhost:123 [proxy] tcp://localhost:1234
45
public function testThrowsExceptionsCaughtDuringTransfer()
48
$client = new Client([
49
'adapter' => new StreamAdapter(new MessageFactory()),
51
$client->get('http://localhost:123', [
53
'proxy' => 'tcp://localhost:1234'
58
* @expectedException \GuzzleHttp\Exception\RequestException
59
* @expectedExceptionMessage URL is invalid: ftp://localhost:123
61
public function testEnsuresTheHttpProtocol()
64
$client = new Client([
65
'adapter' => new StreamAdapter(new MessageFactory()),
67
$client->get('ftp://localhost:123');
70
public function testCanHandleExceptionsUsingEvents()
73
$client = new Client([
74
'adapter' => new StreamAdapter(new MessageFactory())
76
$request = $client->createRequest('GET', Server::$url);
77
$mockResponse = new Response(200);
78
$request->getEmitter()->on(
80
function (ErrorEvent $e) use ($mockResponse) {
81
$e->intercept($mockResponse);
84
$this->assertSame($mockResponse, $client->send($request));
87
public function testEmitsAfterSendEvent()
92
"HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there"
94
$client = new Client(['adapter' => new StreamAdapter(new MessageFactory())]);
95
$request = $client->createRequest('GET', Server::$url);
96
$request->getEmitter()->on('complete', function ($e) use (&$ee) {
99
$client->send($request);
100
$this->assertInstanceOf('GuzzleHttp\Event\CompleteEvent', $ee);
101
$this->assertSame($request, $ee->getRequest());
102
$this->assertEquals(200, $ee->getResponse()->getStatusCode());
105
public function testStreamAttributeKeepsStreamOpen()
109
"HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there"
111
$client = new Client([
112
'base_url' => Server::$url,
113
'adapter' => new StreamAdapter(new MessageFactory())
115
$response = $client->put('/foo', [
116
'headers' => ['Foo' => 'Bar'],
120
$this->assertEquals(200, $response->getStatusCode());
121
$this->assertEquals('OK', $response->getReasonPhrase());
122
$this->assertEquals('8', $response->getHeader('Content-Length'));
123
$body = $response->getBody();
124
if (defined('HHVM_VERSION')) {
125
$this->markTestIncomplete('HHVM has not implemented this?');
127
$this->assertEquals('http', $body->getMetadata()['wrapper_type']);
128
$this->assertEquals(Server::$url . 'foo', $body->getMetadata()['uri']);
129
$this->assertEquals('hi', $body->read(2));
132
$sent = Server::received(true)[0];
133
$this->assertEquals('PUT', $sent->getMethod());
134
$this->assertEquals('/foo', $sent->getResource());
135
$this->assertEquals('127.0.0.1:8125', $sent->getHeader('host'));
136
$this->assertEquals('Bar', $sent->getHeader('foo'));
137
$this->assertTrue($sent->hasHeader('user-agent'));
140
public function testDrainsResponseIntoTempStream()
143
Server::enqueue("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there");
144
$client = new Client([
145
'base_url' => Server::$url,
146
'adapter' => new StreamAdapter(new MessageFactory())
148
$response = $client->get('/');
149
$body = $response->getBody();
150
$this->assertEquals('php://temp', $body->getMetadata()['uri']);
151
$this->assertEquals('hi', $body->read(2));
155
public function testDrainsResponseIntoSaveToBody()
157
$r = fopen('php://temp', 'r+');
159
Server::enqueue("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there");
160
$client = new Client([
161
'base_url' => Server::$url,
162
'adapter' => new StreamAdapter(new MessageFactory())
164
$response = $client->get('/', ['save_to' => $r]);
165
$body = $response->getBody();
166
$this->assertEquals('php://temp', $body->getMetadata()['uri']);
167
$this->assertEquals('hi', $body->read(2));
168
$this->assertEquals(' there', stream_get_contents($r));
172
public function testDrainsResponseIntoSaveToBodyAtPath()
174
$tmpfname = tempnam('/tmp', 'save_to_path');
176
Server::enqueue("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there");
177
$client = new Client([
178
'base_url' => Server::$url,
179
'adapter' => new StreamAdapter(new MessageFactory())
181
$response = $client->get('/', ['save_to' => $tmpfname]);
182
$body = $response->getBody();
183
$this->assertEquals($tmpfname, $body->getMetadata()['uri']);
184
$this->assertEquals('hi', $body->read(2));
189
public function testAutomaticallyDecompressGzip()
192
$content = gzencode('test');
193
$message = "HTTP/1.1 200 OK\r\n"
195
. "Content-Encoding: gzip\r\n"
196
. "Content-Length: " . strlen($content) . "\r\n\r\n"
198
Server::enqueue($message);
199
$client = new Client([
200
'base_url' => Server::$url,
201
'adapter' => new StreamAdapter(new MessageFactory())
203
$response = $client->get('/', ['stream' => true]);
204
$body = $response->getBody();
205
$this->assertEquals('guzzle://stream', $body->getMetadata()['uri']);
206
$this->assertEquals('test', (string) $body);
209
public function testDoesNotForceDecode()
212
$content = gzencode('test');
213
$message = "HTTP/1.1 200 OK\r\n"
215
. "Content-Encoding: gzip\r\n"
216
. "Content-Length: " . strlen($content) . "\r\n\r\n"
218
Server::enqueue($message);
219
$client = new Client([
220
'base_url' => Server::$url,
221
'adapter' => new StreamAdapter(new MessageFactory())
223
$response = $client->get('/', [
224
'decode_content' => false,
227
$body = $response->getBody();
228
$this->assertSame($content, (string) $body);
231
protected function getStreamFromBody(Stream $body)
233
$r = new \ReflectionProperty($body, 'stream');
234
$r->setAccessible(true);
236
return $r->getValue($body);
239
protected function getSendResult(array $opts)
241
Server::enqueue("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there");
242
$client = new Client(['adapter' => new StreamAdapter(new MessageFactory())]);
244
return $client->get(Server::$url, $opts);
247
public function testAddsProxy()
249
$body = $this->getSendResult(['stream' => true, 'proxy' => '127.0.0.1:8125'])->getBody();
250
$opts = stream_context_get_options($this->getStreamFromBody($body));
251
$this->assertEquals('127.0.0.1:8125', $opts['http']['proxy']);
254
public function testAddsTimeout()
256
$body = $this->getSendResult(['stream' => true, 'timeout' => 200])->getBody();
257
$opts = stream_context_get_options($this->getStreamFromBody($body));
258
$this->assertEquals(200, $opts['http']['timeout']);
262
* @expectedException \RuntimeException
263
* @expectedExceptionMessage SSL certificate authority file not found: /does/not/exist
265
public function testVerifiesVerifyIsValidIfPath()
268
'adapter' => new StreamAdapter(new MessageFactory()),
269
'base_url' => Server::$url,
270
'defaults' => ['verify' => '/does/not/exist']
274
public function testVerifyCanBeDisabled()
276
Server::enqueue("HTTP/1.1 200\r\nContent-Length: 0\r\n\r\n");
278
'adapter' => new StreamAdapter(new MessageFactory()),
279
'base_url' => Server::$url,
280
'defaults' => ['verify' => false]
284
public function testVerifyCanBeSetToPath()
286
$path = __DIR__ . '/../../src/cacert.pem';
287
$this->assertFileExists($path);
288
$body = $this->getSendResult(['stream' => true, 'verify' => $path])->getBody();
289
$opts = stream_context_get_options($this->getStreamFromBody($body));
290
$this->assertEquals(true, $opts['http']['verify_peer']);
291
$this->assertEquals($path, $opts['http']['cafile']);
292
$this->assertTrue(file_exists($opts['http']['cafile']));
296
* @expectedException \RuntimeException
297
* @expectedExceptionMessage SSL certificate not found: /does/not/exist
299
public function testVerifiesCertIfValidPath()
302
'adapter' => new StreamAdapter(new MessageFactory()),
303
'base_url' => Server::$url,
304
'defaults' => ['cert' => '/does/not/exist']
308
public function testCanSetPasswordWhenSettingCert()
310
$path = __DIR__ . '/../../src/cacert.pem';
311
$body = $this->getSendResult(['stream' => true, 'cert' => [$path, 'foo']])->getBody();
312
$opts = stream_context_get_options($this->getStreamFromBody($body));
313
$this->assertEquals($path, $opts['http']['local_cert']);
314
$this->assertEquals('foo', $opts['http']['passphrase']);
317
public function testDebugAttributeWritesStreamInfoToTempBufferByDefault()
319
if (defined('HHVM_VERSION')) {
320
$this->markTestSkipped('HHVM has not implemented this?');
325
Server::enqueue("HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there");
326
$client = new Client([
327
'base_url' => Server::$url,
328
'adapter' => new StreamAdapter(new MessageFactory())
330
$fp = fopen('php://temp', 'w');
331
$client->get('/', ['debug' => $fp]);
333
$contents = stream_get_contents($fp);
334
$this->assertContains('<http://127.0.0.1:8125/> [CONNECT]', $contents);
335
$this->assertContains('<http://127.0.0.1:8125/> [FILE_SIZE_IS]', $contents);
336
$this->assertContains('<http://127.0.0.1:8125/> [PROGRESS]', $contents);
339
public function testDebugAttributeWritesStreamInfoToBuffer()
341
if (defined('HHVM_VERSION')) {
342
$this->markTestSkipped('HHVM has not implemented this?');
346
$buffer = fopen('php://temp', 'r+');
348
Server::enqueue("HTTP/1.1 200 OK\r\nContent-Length: 8\r\nContent-Type: text/plain\r\n\r\nhi there");
349
$client = new Client([
350
'base_url' => Server::$url,
351
'adapter' => new StreamAdapter(new MessageFactory())
353
$client->get('/', ['debug' => $buffer]);
355
$contents = stream_get_contents($buffer);
356
$this->assertContains('<http://127.0.0.1:8125/> [CONNECT]', $contents);
357
$this->assertContains('<http://127.0.0.1:8125/> [FILE_SIZE_IS] message: "Content-Length: 8"', $contents);
358
$this->assertContains('<http://127.0.0.1:8125/> [PROGRESS] bytes_max: "8"', $contents);
359
$this->assertContains('<http://127.0.0.1:8125/> [MIME_TYPE_IS] message: "text/plain"', $contents);
362
public function testAddsProxyByProtocol()
364
$url = str_replace('http', 'tcp', Server::$url);
365
$body = $this->getSendResult(['stream' => true, 'proxy' => ['http' => $url]])->getBody();
366
$opts = stream_context_get_options($this->getStreamFromBody($body));
367
$this->assertEquals($url, $opts['http']['proxy']);
370
public function testPerformsShallowMergeOfCustomContextOptions()
372
$body = $this->getSendResult([
375
'stream_context' => [
377
'request_fulluri' => true,
381
'bindto' => '127.0.0.1:0'
384
'verify_peer' => false
390
$opts = stream_context_get_options($this->getStreamFromBody($body));
391
$this->assertEquals('HEAD', $opts['http']['method']);
392
$this->assertTrue($opts['http']['request_fulluri']);
393
$this->assertFalse($opts['ssl']['verify_peer']);
394
$this->assertEquals('127.0.0.1:0', $opts['socket']['bindto']);
398
* @expectedException \GuzzleHttp\Exception\RequestException
399
* @expectedExceptionMessage stream_context must be an array
401
public function testEnsuresThatStreamContextIsAnArray()
403
$this->getSendResult([
405
'config' => ['stream_context' => 'foo']
410
* @ticket https://github.com/guzzle/guzzle/issues/725
412
public function testHandlesMultipleHeadersOfSameName()
414
$a = new StreamAdapter(new MessageFactory());
415
$ref = new \ReflectionMethod($a, 'headersFromLines');
416
$ref->setAccessible(true);
417
$this->assertEquals([
418
'foo' => ['bar', 'bam'],
420
], $ref->invoke($a, [
427
public function testDoesNotAddContentTypeByDefault()
430
Server::enqueue("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
431
$client = new Client([
432
'base_url' => Server::$url,
433
'adapter' => new StreamAdapter(new MessageFactory())
435
$client->put('/', ['body' => 'foo']);
436
$requests = Server::received(true);
437
$this->assertEquals('', $requests[0]->getHeader('Content-Type'));
438
$this->assertEquals(3, $requests[0]->getHeader('Content-Length'));