scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 1 <?php
2 namespace GuzzleHttp\Tests\Adapter;
3  
4 use GuzzleHttp\Adapter\StreamAdapter;
5 use GuzzleHttp\Client;
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;
11  
12 /**
13 * @covers GuzzleHttp\Adapter\StreamAdapter
14 */
15 class StreamAdapterTest extends \PHPUnit_Framework_TestCase
16 {
17 public function testReturnsResponseForSuccessfulRequest()
18 {
19 Server::flush();
20 Server::enqueue(
21 "HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 2\r\n\r\nhi"
22 );
23 $client = new Client([
24 'base_url' => Server::$url,
25 'adapter' => new StreamAdapter(new MessageFactory())
26 ]);
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'));
39 }
40  
41 /**
42 * @expectedException \GuzzleHttp\Exception\RequestException
43 * @expectedExceptionMessage Error creating resource. [url] http://localhost:123 [proxy] tcp://localhost:1234
44 */
45 public function testThrowsExceptionsCaughtDuringTransfer()
46 {
47 Server::flush();
48 $client = new Client([
49 'adapter' => new StreamAdapter(new MessageFactory()),
50 ]);
51 $client->get('http://localhost:123', [
52 'timeout' => 0.01,
53 'proxy' => 'tcp://localhost:1234'
54 ]);
55 }
56  
57 /**
58 * @expectedException \GuzzleHttp\Exception\RequestException
59 * @expectedExceptionMessage URL is invalid: ftp://localhost:123
60 */
61 public function testEnsuresTheHttpProtocol()
62 {
63 Server::flush();
64 $client = new Client([
65 'adapter' => new StreamAdapter(new MessageFactory()),
66 ]);
67 $client->get('ftp://localhost:123');
68 }
69  
70 public function testCanHandleExceptionsUsingEvents()
71 {
72 Server::flush();
73 $client = new Client([
74 'adapter' => new StreamAdapter(new MessageFactory())
75 ]);
76 $request = $client->createRequest('GET', Server::$url);
77 $mockResponse = new Response(200);
78 $request->getEmitter()->on(
79 'error',
80 function (ErrorEvent $e) use ($mockResponse) {
81 $e->intercept($mockResponse);
82 }
83 );
84 $this->assertSame($mockResponse, $client->send($request));
85 }
86  
87 public function testEmitsAfterSendEvent()
88 {
89 $ee = null;
90 Server::flush();
91 Server::enqueue(
92 "HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there"
93 );
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) {
97 $ee = $e;
98 });
99 $client->send($request);
100 $this->assertInstanceOf('GuzzleHttp\Event\CompleteEvent', $ee);
101 $this->assertSame($request, $ee->getRequest());
102 $this->assertEquals(200, $ee->getResponse()->getStatusCode());
103 }
104  
105 public function testStreamAttributeKeepsStreamOpen()
106 {
107 Server::flush();
108 Server::enqueue(
109 "HTTP/1.1 200 OK\r\nFoo: Bar\r\nContent-Length: 8\r\n\r\nhi there"
110 );
111 $client = new Client([
112 'base_url' => Server::$url,
113 'adapter' => new StreamAdapter(new MessageFactory())
114 ]);
115 $response = $client->put('/foo', [
116 'headers' => ['Foo' => 'Bar'],
117 'body' => 'test',
118 'stream' => true
119 ]);
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?');
126 }
127 $this->assertEquals('http', $body->getMetadata()['wrapper_type']);
128 $this->assertEquals(Server::$url . 'foo', $body->getMetadata()['uri']);
129 $this->assertEquals('hi', $body->read(2));
130 $body->close();
131  
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'));
138 }
139  
140 public function testDrainsResponseIntoTempStream()
141 {
142 Server::flush();
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())
147 ]);
148 $response = $client->get('/');
149 $body = $response->getBody();
150 $this->assertEquals('php://temp', $body->getMetadata()['uri']);
151 $this->assertEquals('hi', $body->read(2));
152 $body->close();
153 }
154  
155 public function testDrainsResponseIntoSaveToBody()
156 {
157 $r = fopen('php://temp', 'r+');
158 Server::flush();
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())
163 ]);
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));
169 $body->close();
170 }
171  
172 public function testDrainsResponseIntoSaveToBodyAtPath()
173 {
174 $tmpfname = tempnam('/tmp', 'save_to_path');
175 Server::flush();
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())
180 ]);
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));
185 $body->close();
186 unlink($tmpfname);
187 }
188  
189 public function testAutomaticallyDecompressGzip()
190 {
191 Server::flush();
192 $content = gzencode('test');
193 $message = "HTTP/1.1 200 OK\r\n"
194 . "Foo: Bar\r\n"
195 . "Content-Encoding: gzip\r\n"
196 . "Content-Length: " . strlen($content) . "\r\n\r\n"
197 . $content;
198 Server::enqueue($message);
199 $client = new Client([
200 'base_url' => Server::$url,
201 'adapter' => new StreamAdapter(new MessageFactory())
202 ]);
203 $response = $client->get('/', ['stream' => true]);
204 $body = $response->getBody();
205 $this->assertEquals('guzzle://stream', $body->getMetadata()['uri']);
206 $this->assertEquals('test', (string) $body);
207 }
208  
209 public function testDoesNotForceDecode()
210 {
211 Server::flush();
212 $content = gzencode('test');
213 $message = "HTTP/1.1 200 OK\r\n"
214 . "Foo: Bar\r\n"
215 . "Content-Encoding: gzip\r\n"
216 . "Content-Length: " . strlen($content) . "\r\n\r\n"
217 . $content;
218 Server::enqueue($message);
219 $client = new Client([
220 'base_url' => Server::$url,
221 'adapter' => new StreamAdapter(new MessageFactory())
222 ]);
223 $response = $client->get('/', [
224 'decode_content' => false,
225 'stream' => true
226 ]);
227 $body = $response->getBody();
228 $this->assertSame($content, (string) $body);
229 }
230  
231 protected function getStreamFromBody(Stream $body)
232 {
233 $r = new \ReflectionProperty($body, 'stream');
234 $r->setAccessible(true);
235  
236 return $r->getValue($body);
237 }
238  
239 protected function getSendResult(array $opts)
240 {
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())]);
243  
244 return $client->get(Server::$url, $opts);
245 }
246  
247 public function testAddsProxy()
248 {
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']);
252 }
253  
254 public function testAddsTimeout()
255 {
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']);
259 }
260  
261 /**
262 * @expectedException \RuntimeException
263 * @expectedExceptionMessage SSL certificate authority file not found: /does/not/exist
264 */
265 public function testVerifiesVerifyIsValidIfPath()
266 {
267 (new Client([
268 'adapter' => new StreamAdapter(new MessageFactory()),
269 'base_url' => Server::$url,
270 'defaults' => ['verify' => '/does/not/exist']
271 ]))->get('/');
272 }
273  
274 public function testVerifyCanBeDisabled()
275 {
276 Server::enqueue("HTTP/1.1 200\r\nContent-Length: 0\r\n\r\n");
277 (new Client([
278 'adapter' => new StreamAdapter(new MessageFactory()),
279 'base_url' => Server::$url,
280 'defaults' => ['verify' => false]
281 ]))->get('/');
282 }
283  
284 public function testVerifyCanBeSetToPath()
285 {
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']));
293 }
294  
295 /**
296 * @expectedException \RuntimeException
297 * @expectedExceptionMessage SSL certificate not found: /does/not/exist
298 */
299 public function testVerifiesCertIfValidPath()
300 {
301 (new Client([
302 'adapter' => new StreamAdapter(new MessageFactory()),
303 'base_url' => Server::$url,
304 'defaults' => ['cert' => '/does/not/exist']
305 ]))->get('/');
306 }
307  
308 public function testCanSetPasswordWhenSettingCert()
309 {
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']);
315 }
316  
317 public function testDebugAttributeWritesStreamInfoToTempBufferByDefault()
318 {
319 if (defined('HHVM_VERSION')) {
320 $this->markTestSkipped('HHVM has not implemented this?');
321 return;
322 }
323  
324 Server::flush();
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())
329 ]);
330 $fp = fopen('php://temp', 'w');
331 $client->get('/', ['debug' => $fp]);
332 fseek($fp, 0);
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);
337 }
338  
339 public function testDebugAttributeWritesStreamInfoToBuffer()
340 {
341 if (defined('HHVM_VERSION')) {
342 $this->markTestSkipped('HHVM has not implemented this?');
343 return;
344 }
345  
346 $buffer = fopen('php://temp', 'r+');
347 Server::flush();
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())
352 ]);
353 $client->get('/', ['debug' => $buffer]);
354 fseek($buffer, 0);
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);
360 }
361  
362 public function testAddsProxyByProtocol()
363 {
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']);
368 }
369  
370 public function testPerformsShallowMergeOfCustomContextOptions()
371 {
372 $body = $this->getSendResult([
373 'stream' => true,
374 'config' => [
375 'stream_context' => [
376 'http' => [
377 'request_fulluri' => true,
378 'method' => 'HEAD'
379 ],
380 'socket' => [
381 'bindto' => '127.0.0.1:0'
382 ],
383 'ssl' => [
384 'verify_peer' => false
385 ]
386 ]
387 ]
388 ])->getBody();
389  
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']);
395 }
396  
397 /**
398 * @expectedException \GuzzleHttp\Exception\RequestException
399 * @expectedExceptionMessage stream_context must be an array
400 */
401 public function testEnsuresThatStreamContextIsAnArray()
402 {
403 $this->getSendResult([
404 'stream' => true,
405 'config' => ['stream_context' => 'foo']
406 ]);
407 }
408  
409 /**
410 * @ticket https://github.com/guzzle/guzzle/issues/725
411 */
412 public function testHandlesMultipleHeadersOfSameName()
413 {
414 $a = new StreamAdapter(new MessageFactory());
415 $ref = new \ReflectionMethod($a, 'headersFromLines');
416 $ref->setAccessible(true);
417 $this->assertEquals([
418 'foo' => ['bar', 'bam'],
419 'abc' => ['123']
420 ], $ref->invoke($a, [
421 'foo: bar',
422 'foo: bam',
423 'abc: 123'
424 ]));
425 }
426  
427 public function testDoesNotAddContentTypeByDefault()
428 {
429 Server::flush();
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())
434 ]);
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'));
439 }
440 }