/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php
PHP | 1764 lines | 1222 code | 213 blank | 329 comment | 6 complexity | 26a45281c8ecac695e15f5bc26509e1f MD5 | raw file
1<?php 2/** 3 * HttpSocketTest file 4 * 5 * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html> 6 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) 7 * 8 * Licensed under The MIT License 9 * For full copyright and license information, please see the LICENSE.txt 10 * Redistributions of files must retain the above copyright notice 11 * 12 * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) 13 * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests 14 * @package Cake.Test.Case.Network.Http 15 * @since CakePHP(tm) v 1.2.0.4206 16 * @license http://www.opensource.org/licenses/mit-license.php MIT License 17 */ 18 19App::uses('HttpSocket', 'Network/Http'); 20App::uses('HttpResponse', 'Network/Http'); 21 22/** 23 * TestAuthentication class 24 * 25 * @package Cake.Test.Case.Network.Http 26 */ 27class TestAuthentication { 28 29/** 30 * authentication method 31 * 32 * @param HttpSocket $http 33 * @param array $authInfo 34 * @return void 35 */ 36 public static function authentication(HttpSocket $http, &$authInfo) { 37 $http->request['header']['Authorization'] = 'Test ' . $authInfo['user'] . '.' . $authInfo['pass']; 38 } 39 40/** 41 * proxyAuthentication method 42 * 43 * @param HttpSocket $http 44 * @param array $proxyInfo 45 * @return void 46 */ 47 public static function proxyAuthentication(HttpSocket $http, &$proxyInfo) { 48 $http->request['header']['Proxy-Authorization'] = 'Test ' . $proxyInfo['user'] . '.' . $proxyInfo['pass']; 49 } 50 51} 52 53/** 54 * CustomResponse 55 * 56 */ 57class CustomResponse { 58 59/** 60 * First 10 chars 61 * 62 * @var string 63 */ 64 public $first10; 65 66/** 67 * Constructor 68 * 69 */ 70 public function __construct($message) { 71 $this->first10 = substr($message, 0, 10); 72 } 73 74} 75 76/** 77 * TestHttpSocket 78 * 79 */ 80class TestHttpSocket extends HttpSocket { 81 82/** 83 * Convenience method for testing protected method 84 * 85 * @param string|array $uri URI (see {@link _parseUri()}) 86 * @return array Current configuration settings 87 */ 88 public function configUri($uri = null) { 89 return parent::_configUri($uri); 90 } 91 92/** 93 * Convenience method for testing protected method 94 * 95 * @param string|array $uri URI to parse 96 * @param boolean|array $base If true use default URI config, otherwise indexed array to set 'scheme', 'host', 'port', etc. 97 * @return array Parsed URI 98 */ 99 public function parseUri($uri = null, $base = array()) { 100 return parent::_parseUri($uri, $base); 101 } 102 103/** 104 * Convenience method for testing protected method 105 * 106 * @param array $uri A $uri array, or uses $this->config if left empty 107 * @param string $uriTemplate The Uri template/format to use 108 * @return string A fully qualified URL formatted according to $uriTemplate 109 */ 110 public function buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { 111 return parent::_buildUri($uri, $uriTemplate); 112 } 113 114/** 115 * Convenience method for testing protected method 116 * 117 * @param array $header Header to build 118 * @return string Header built from array 119 */ 120 public function buildHeader($header, $mode = 'standard') { 121 return parent::_buildHeader($header, $mode); 122 } 123 124/** 125 * Convenience method for testing protected method 126 * 127 * @param string|array $query A query string to parse into an array or an array to return directly "as is" 128 * @return array The $query parsed into a possibly multi-level array. If an empty $query is given, an empty array is returned. 129 */ 130 public function parseQuery($query) { 131 return parent::_parseQuery($query); 132 } 133 134/** 135 * Convenience method for testing protected method 136 * 137 * @param array $request Needs to contain a 'uri' key. Should also contain a 'method' key, otherwise defaults to GET. 138 * @param string $versionToken The version token to use, defaults to HTTP/1.1 139 * @return string Request line 140 */ 141 public function buildRequestLine($request = array(), $versionToken = 'HTTP/1.1') { 142 return parent::_buildRequestLine($request, $versionToken); 143 } 144 145/** 146 * Convenience method for testing protected method 147 * 148 * @param boolean $hex true to get them as HEX values, false otherwise 149 * @return array Escape chars 150 */ 151 public function tokenEscapeChars($hex = true, $chars = null) { 152 return parent::_tokenEscapeChars($hex, $chars); 153 } 154 155/** 156 * Convenience method for testing protected method 157 * 158 * @param string $token Token to escape 159 * @return string Escaped token 160 */ 161 public function escapeToken($token, $chars = null) { 162 return parent::_escapeToken($token, $chars); 163 } 164 165} 166 167/** 168 * HttpSocketTest class 169 * 170 * @package Cake.Test.Case.Network.Http 171 */ 172class HttpSocketTest extends CakeTestCase { 173 174/** 175 * Socket property 176 * 177 * @var mixed null 178 */ 179 public $Socket = null; 180 181/** 182 * RequestSocket property 183 * 184 * @var mixed null 185 */ 186 public $RequestSocket = null; 187 188/** 189 * This function sets up a TestHttpSocket instance we are going to use for testing 190 * 191 * @return void 192 */ 193 public function setUp() { 194 parent::setUp(); 195 if (!class_exists('MockHttpSocket')) { 196 $this->getMock('TestHttpSocket', array('read', 'write', 'connect'), array(), 'MockHttpSocket'); 197 $this->getMock('TestHttpSocket', array('read', 'write', 'connect', 'request'), array(), 'MockHttpSocketRequests'); 198 } 199 200 $this->Socket = new MockHttpSocket(); 201 $this->RequestSocket = new MockHttpSocketRequests(); 202 } 203 204/** 205 * We use this function to clean up after the test case was executed 206 * 207 * @return void 208 */ 209 public function tearDown() { 210 parent::tearDown(); 211 unset($this->Socket, $this->RequestSocket); 212 } 213 214/** 215 * Test that HttpSocket::__construct does what one would expect it to do 216 * 217 * @return void 218 */ 219 public function testConstruct() { 220 $this->Socket->reset(); 221 $baseConfig = $this->Socket->config; 222 $this->Socket->expects($this->never())->method('connect'); 223 $this->Socket->__construct(array('host' => 'foo-bar')); 224 $baseConfig['host'] = 'foo-bar'; 225 $baseConfig['protocol'] = getprotobyname($baseConfig['protocol']); 226 $this->assertEquals($this->Socket->config, $baseConfig); 227 228 $this->Socket->reset(); 229 $baseConfig = $this->Socket->config; 230 $this->Socket->__construct('http://www.cakephp.org:23/'); 231 $baseConfig['host'] = $baseConfig['request']['uri']['host'] = 'www.cakephp.org'; 232 $baseConfig['port'] = $baseConfig['request']['uri']['port'] = 23; 233 $baseConfig['request']['uri']['scheme'] = 'http'; 234 $baseConfig['protocol'] = getprotobyname($baseConfig['protocol']); 235 $this->assertEquals($this->Socket->config, $baseConfig); 236 237 $this->Socket->reset(); 238 $this->Socket->__construct(array('request' => array('uri' => 'http://www.cakephp.org:23/'))); 239 $this->assertEquals($this->Socket->config, $baseConfig); 240 } 241 242/** 243 * Test that HttpSocket::configUri works properly with different types of arguments 244 * 245 * @return void 246 */ 247 public function testConfigUri() { 248 $this->Socket->reset(); 249 $r = $this->Socket->configUri('https://bob:secret@www.cakephp.org:23/?query=foo'); 250 $expected = array( 251 'persistent' => false, 252 'host' => 'www.cakephp.org', 253 'protocol' => 'tcp', 254 'port' => 23, 255 'timeout' => 30, 256 'ssl_verify_peer' => true, 257 'ssl_allow_self_signed' => false, 258 'ssl_verify_depth' => 5, 259 'ssl_verify_host' => true, 260 'request' => array( 261 'uri' => array( 262 'scheme' => 'https', 263 'host' => 'www.cakephp.org', 264 'port' => 23 265 ), 266 'redirect' => false, 267 'cookies' => array(), 268 ) 269 ); 270 $this->assertEquals($expected, $this->Socket->config); 271 $this->assertTrue($r); 272 $r = $this->Socket->configUri(array('host' => 'www.foo-bar.org')); 273 $expected['host'] = 'www.foo-bar.org'; 274 $expected['request']['uri']['host'] = 'www.foo-bar.org'; 275 $this->assertEquals($expected, $this->Socket->config); 276 $this->assertTrue($r); 277 278 $r = $this->Socket->configUri('http://www.foo.com'); 279 $expected = array( 280 'persistent' => false, 281 'host' => 'www.foo.com', 282 'protocol' => 'tcp', 283 'port' => 80, 284 'timeout' => 30, 285 'ssl_verify_peer' => true, 286 'ssl_allow_self_signed' => false, 287 'ssl_verify_depth' => 5, 288 'ssl_verify_host' => true, 289 'request' => array( 290 'uri' => array( 291 'scheme' => 'http', 292 'host' => 'www.foo.com', 293 'port' => 80 294 ), 295 'redirect' => false, 296 'cookies' => array(), 297 ) 298 ); 299 $this->assertEquals($expected, $this->Socket->config); 300 $this->assertTrue($r); 301 302 $r = $this->Socket->configUri('/this-is-broken'); 303 $this->assertEquals($expected, $this->Socket->config); 304 $this->assertFalse($r); 305 306 $r = $this->Socket->configUri(false); 307 $this->assertEquals($expected, $this->Socket->config); 308 $this->assertFalse($r); 309 } 310 311/** 312 * Tests that HttpSocket::request (the heart of the HttpSocket) is working properly. 313 * 314 * @return void 315 */ 316 public function testRequest() { 317 $this->Socket->reset(); 318 319 $response = $this->Socket->request(true); 320 $this->assertFalse($response); 321 322 $context = array( 323 'ssl' => array( 324 'verify_peer' => true, 325 'allow_self_signed' => false, 326 'verify_depth' => 5, 327 'CN_match' => 'www.cakephp.org', 328 'cafile' => CAKE . 'Config' . DS . 'cacert.pem' 329 ) 330 ); 331 332 $tests = array( 333 array( 334 'request' => 'http://www.cakephp.org/?foo=bar', 335 'expectation' => array( 336 'config' => array( 337 'persistent' => false, 338 'host' => 'www.cakephp.org', 339 'protocol' => 'tcp', 340 'port' => 80, 341 'timeout' => 30, 342 'context' => $context, 343 'request' => array( 344 'uri' => array( 345 'scheme' => 'http', 346 'host' => 'www.cakephp.org', 347 'port' => 80 348 ), 349 'redirect' => false, 350 'cookies' => array() 351 ) 352 ), 353 'request' => array( 354 'method' => 'GET', 355 'uri' => array( 356 'scheme' => 'http', 357 'host' => 'www.cakephp.org', 358 'port' => 80, 359 'user' => null, 360 'pass' => null, 361 'path' => '/', 362 'query' => array('foo' => 'bar'), 363 'fragment' => null 364 ), 365 'version' => '1.1', 366 'body' => '', 367 'line' => "GET /?foo=bar HTTP/1.1\r\n", 368 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n", 369 'raw' => "", 370 'redirect' => false, 371 'cookies' => array(), 372 'proxy' => array(), 373 'auth' => array() 374 ) 375 ) 376 ), 377 array( 378 'request' => array( 379 'uri' => array( 380 'host' => 'www.cakephp.org', 381 'query' => '?foo=bar' 382 ) 383 ) 384 ), 385 array( 386 'request' => 'www.cakephp.org/?foo=bar' 387 ), 388 array( 389 'request' => array( 390 'host' => '192.168.0.1', 391 'uri' => 'http://www.cakephp.org/?foo=bar' 392 ), 393 'expectation' => array( 394 'request' => array( 395 'uri' => array('host' => 'www.cakephp.org') 396 ), 397 'config' => array( 398 'request' => array( 399 'uri' => array('host' => 'www.cakephp.org') 400 ), 401 'host' => '192.168.0.1' 402 ) 403 ) 404 ), 405 'reset4' => array( 406 'request.uri.query' => array() 407 ), 408 array( 409 'request' => array( 410 'header' => array('Foo@woo' => 'bar-value') 411 ), 412 'expectation' => array( 413 'request' => array( 414 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n", 415 'line' => "GET / HTTP/1.1\r\n" 416 ) 417 ) 418 ), 419 array( 420 'request' => array('header' => array('Foo@woo' => 'bar-value', 'host' => 'foo.com'), 'uri' => 'http://www.cakephp.org/'), 421 'expectation' => array( 422 'request' => array( 423 'header' => "Host: foo.com\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n" 424 ), 425 'config' => array( 426 'host' => 'www.cakephp.org' 427 ) 428 ) 429 ), 430 array( 431 'request' => array('header' => "Foo: bar\r\n"), 432 'expectation' => array( 433 'request' => array( 434 'header' => "Foo: bar\r\n" 435 ) 436 ) 437 ), 438 array( 439 'request' => array('header' => "Foo: bar\r\n", 'uri' => 'http://www.cakephp.org/search?q=http_socket#ignore-me'), 440 'expectation' => array( 441 'request' => array( 442 'uri' => array( 443 'path' => '/search', 444 'query' => array('q' => 'http_socket'), 445 'fragment' => 'ignore-me' 446 ), 447 'line' => "GET /search?q=http_socket HTTP/1.1\r\n" 448 ) 449 ) 450 ), 451 'reset8' => array( 452 'request.uri.query' => array() 453 ), 454 array( 455 'request' => array( 456 'method' => 'POST', 457 'uri' => 'http://www.cakephp.org/posts/add', 458 'body' => array( 459 'name' => 'HttpSocket-is-released', 460 'date' => 'today' 461 ) 462 ), 463 'expectation' => array( 464 'request' => array( 465 'method' => 'POST', 466 'uri' => array( 467 'path' => '/posts/add', 468 'fragment' => null 469 ), 470 'body' => "name=HttpSocket-is-released&date=today", 471 'line' => "POST /posts/add HTTP/1.1\r\n", 472 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n", 473 'raw' => "name=HttpSocket-is-released&date=today" 474 ) 475 ) 476 ), 477 array( 478 'request' => array( 479 'method' => 'POST', 480 'uri' => 'http://www.cakephp.org:8080/posts/add', 481 'body' => array( 482 'name' => 'HttpSocket-is-released', 483 'date' => 'today' 484 ) 485 ), 486 'expectation' => array( 487 'config' => array( 488 'port' => 8080, 489 'request' => array( 490 'uri' => array( 491 'port' => 8080 492 ) 493 ) 494 ), 495 'request' => array( 496 'uri' => array( 497 'port' => 8080 498 ), 499 'header' => "Host: www.cakephp.org:8080\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" 500 ) 501 ) 502 ), 503 array( 504 'request' => array( 505 'method' => 'POST', 506 'uri' => 'https://www.cakephp.org/posts/add', 507 'body' => array( 508 'name' => 'HttpSocket-is-released', 509 'date' => 'today' 510 ) 511 ), 512 'expectation' => array( 513 'config' => array( 514 'port' => 443, 515 'request' => array( 516 'uri' => array( 517 'scheme' => 'https', 518 'port' => 443 519 ) 520 ) 521 ), 522 'request' => array( 523 'uri' => array( 524 'scheme' => 'https', 525 'port' => 443 526 ), 527 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" 528 ) 529 ) 530 ), 531 array( 532 'request' => array( 533 'method' => 'POST', 534 'uri' => 'https://www.cakephp.org/posts/add', 535 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'), 536 'cookies' => array('foo' => array('value' => 'bar')) 537 ), 538 'expectation' => array( 539 'request' => array( 540 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\nCookie: foo=bar\r\n", 541 'cookies' => array( 542 'foo' => array('value' => 'bar'), 543 ) 544 ) 545 ) 546 ) 547 ); 548 549 $expectation = array(); 550 foreach ($tests as $i => $test) { 551 if (strpos($i, 'reset') === 0) { 552 foreach ($test as $path => $val) { 553 $expectation = Hash::insert($expectation, $path, $val); 554 } 555 continue; 556 } 557 558 if (isset($test['expectation'])) { 559 $expectation = Hash::merge($expectation, $test['expectation']); 560 } 561 $this->Socket->request($test['request']); 562 563 $raw = $expectation['request']['raw']; 564 $expectation['request']['raw'] = $expectation['request']['line'] . $expectation['request']['header'] . "\r\n" . $raw; 565 566 $r = array('config' => $this->Socket->config, 'request' => $this->Socket->request); 567 $this->assertEquals($r, $expectation, 'Failed test #' . $i . ' '); 568 $expectation['request']['raw'] = $raw; 569 } 570 571 $this->Socket->reset(); 572 $request = array('method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')); 573 $response = $this->Socket->request($request); 574 $this->assertEquals("name=HttpSocket-is-released&date=today", $this->Socket->request['body']); 575 } 576 577/** 578 * Test the scheme + port keys 579 * 580 * @return void 581 */ 582 public function testGetWithSchemeAndPort() { 583 $this->Socket->reset(); 584 $request = array( 585 'uri' => array( 586 'scheme' => 'http', 587 'host' => 'cakephp.org', 588 'port' => 8080, 589 'path' => '/', 590 ), 591 'method' => 'GET' 592 ); 593 $this->Socket->request($request); 594 $this->assertContains('Host: cakephp.org:8080', $this->Socket->request['header']); 595 } 596 597/** 598 * Test URLs like http://cakephp.org/index.php?somestring without key/value pair for query 599 * 600 * @return void 601 */ 602 public function testRequestWithStringQuery() { 603 $this->Socket->reset(); 604 $request = array( 605 'uri' => array( 606 'scheme' => 'http', 607 'host' => 'cakephp.org', 608 'path' => 'index.php', 609 'query' => 'somestring' 610 ), 611 'method' => 'GET' 612 ); 613 $this->Socket->request($request); 614 $this->assertContains("GET /index.php?somestring HTTP/1.1", $this->Socket->request['line']); 615 } 616 617/** 618 * The "*" asterisk character is only allowed for the following methods: OPTIONS. 619 * 620 * @expectedException SocketException 621 * @return void 622 */ 623 public function testRequestNotAllowedUri() { 624 $this->Socket->reset(); 625 $request = array('uri' => '*', 'method' => 'GET'); 626 $this->Socket->request($request); 627 } 628 629/** 630 * testRequest2 method 631 * 632 * @return void 633 */ 634 public function testRequest2() { 635 $this->Socket->reset(); 636 $request = array('uri' => 'htpp://www.cakephp.org/'); 637 $number = mt_rand(0, 9999999); 638 $this->Socket->expects($this->once())->method('connect')->will($this->returnValue(true)); 639 $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>Hello, your lucky number is " . $number . "</h1>"; 640 $this->Socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); 641 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 642 $this->Socket->expects($this->once())->method('write') 643 ->with("GET / HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"); 644 $response = (string)$this->Socket->request($request); 645 $this->assertEquals($response, "<h1>Hello, your lucky number is " . $number . "</h1>"); 646 } 647 648/** 649 * testRequest3 method 650 * 651 * @return void 652 */ 653 public function testRequest3() { 654 $request = array('uri' => 'htpp://www.cakephp.org/'); 655 $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a cookie test!</h1>"; 656 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 657 $this->Socket->connected = true; 658 $this->Socket->request($request); 659 $result = $this->Socket->response['cookies']; 660 $expect = array( 661 'foo' => array( 662 'value' => 'bar' 663 ) 664 ); 665 $this->assertEquals($expect, $result); 666 $this->assertEquals($this->Socket->config['request']['cookies']['www.cakephp.org'], $expect); 667 $this->assertFalse($this->Socket->connected); 668 } 669 670/** 671 * testRequestWithConstructor method 672 * 673 * @return void 674 */ 675 public function testRequestWithConstructor() { 676 $request = array( 677 'request' => array( 678 'uri' => array( 679 'scheme' => 'http', 680 'host' => 'localhost', 681 'port' => '5984', 682 'user' => null, 683 'pass' => null 684 ) 685 ) 686 ); 687 $http = new MockHttpSocketRequests($request); 688 689 $expected = array('method' => 'GET', 'uri' => '/_test'); 690 $http->expects($this->at(0))->method('request')->with($expected); 691 $http->get('/_test'); 692 693 $expected = array('method' => 'GET', 'uri' => 'http://localhost:5984/_test?count=4'); 694 $http->expects($this->at(0))->method('request')->with($expected); 695 $http->get('/_test', array('count' => 4)); 696 } 697 698/** 699 * testRequestWithResource 700 * 701 * @return void 702 */ 703 public function testRequestWithResource() { 704 $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a test!</h1>"; 705 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 706 $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); 707 $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse)); 708 $this->Socket->connected = true; 709 710 $f = fopen(TMP . 'download.txt', 'w'); 711 if (!$f) { 712 $this->markTestSkipped('Can not write in TMP directory.'); 713 } 714 715 $this->Socket->setContentResource($f); 716 $result = (string)$this->Socket->request('http://www.cakephp.org/'); 717 $this->assertEquals('', $result); 718 $this->assertEquals('CakeHttp Server', $this->Socket->response['header']['Server']); 719 fclose($f); 720 $this->assertEquals(file_get_contents(TMP . 'download.txt'), '<h1>This is a test!</h1>'); 721 unlink(TMP . 'download.txt'); 722 723 $this->Socket->setContentResource(false); 724 $result = (string)$this->Socket->request('http://www.cakephp.org/'); 725 $this->assertEquals('<h1>This is a test!</h1>', $result); 726 } 727 728/** 729 * testRequestWithCrossCookie 730 * 731 * @return void 732 */ 733 public function testRequestWithCrossCookie() { 734 $this->Socket->connected = true; 735 $this->Socket->config['request']['cookies'] = array(); 736 737 $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a test!</h1>"; 738 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 739 $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); 740 $expected = array('www.cakephp.org' => array('foo' => array('value' => 'bar'))); 741 $this->Socket->request('http://www.cakephp.org/'); 742 $this->assertEquals($expected, $this->Socket->config['request']['cookies']); 743 744 $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: bar=foo\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a test!</h1>"; 745 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 746 $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); 747 $this->Socket->request('http://www.cakephp.org/other'); 748 $this->assertEquals(array('foo' => array('value' => 'bar')), $this->Socket->request['cookies']); 749 $expected['www.cakephp.org'] += array('bar' => array('value' => 'foo')); 750 $this->assertEquals($expected, $this->Socket->config['request']['cookies']); 751 752 $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a test!</h1>"; 753 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 754 $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); 755 $this->Socket->request('/other2'); 756 $this->assertEquals($expected, $this->Socket->config['request']['cookies']); 757 758 $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foobar=ok\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a test!</h1>"; 759 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 760 $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); 761 $this->Socket->request('http://www.cake.com'); 762 $this->assertTrue(empty($this->Socket->request['cookies'])); 763 $expected['www.cake.com'] = array('foobar' => array('value' => 'ok')); 764 $this->assertEquals($expected, $this->Socket->config['request']['cookies']); 765 } 766 767/** 768 * testRequestCustomResponse 769 * 770 * @return void 771 */ 772 public function testRequestCustomResponse() { 773 $this->Socket->connected = true; 774 $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>This is a test!</h1>"; 775 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); 776 $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); 777 778 $this->Socket->responseClass = 'CustomResponse'; 779 $response = $this->Socket->request('http://www.cakephp.org/'); 780 $this->assertInstanceOf('CustomResponse', $response); 781 $this->assertEquals('HTTP/1.x 2', $response->first10); 782 } 783 784/** 785 * Test that redirect URLs are urldecoded 786 * 787 * @return void 788 */ 789 public function testRequestWithRedirectUrlEncoded() { 790 $request = array( 791 'uri' => 'http://localhost/oneuri', 792 'redirect' => 1 793 ); 794 $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://i.cmpnet.com%2Ftechonline%2Fpdf%2Fa.pdf=\r\n\r\n"; 795 $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>You have been redirected</h1>"; 796 797 $this->Socket->expects($this->at(1)) 798 ->method('read') 799 ->will($this->returnValue($serverResponse1)); 800 801 $this->Socket->expects($this->at(3)) 802 ->method('write') 803 ->with($this->logicalAnd( 804 $this->stringContains('Host: i.cmpnet.com'), 805 $this->stringContains('GET /techonline/pdf/a.pdf') 806 )); 807 808 $this->Socket->expects($this->at(4)) 809 ->method('read') 810 ->will($this->returnValue($serverResponse2)); 811 812 $response = $this->Socket->request($request); 813 $this->assertEquals('<h1>You have been redirected</h1>', $response->body()); 814 } 815 816/** 817 * testRequestWithRedirect method 818 * 819 * @return void 820 */ 821 public function testRequestWithRedirectAsTrue() { 822 $request = array( 823 'uri' => 'http://localhost/oneuri', 824 'redirect' => true 825 ); 826 $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; 827 $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>You have been redirected</h1>"; 828 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1)); 829 $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2)); 830 831 $response = $this->Socket->request($request); 832 $this->assertEquals('<h1>You have been redirected</h1>', $response->body()); 833 } 834 835/** 836 * Test that redirects with a count limit are decremented. 837 * 838 * @return void 839 */ 840 public function testRequestWithRedirectAsInt() { 841 $request = array( 842 'uri' => 'http://localhost/oneuri', 843 'redirect' => 2 844 ); 845 $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; 846 $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n<h1>You have been redirected</h1>"; 847 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1)); 848 $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2)); 849 850 $this->Socket->request($request); 851 $this->assertEquals(1, $this->Socket->request['redirect']); 852 } 853 854/** 855 * Test that redirects after the redirect count reaches 9 are not followed. 856 * 857 * @return void 858 */ 859 public function testRequestWithRedirectAsIntReachingZero() { 860 $request = array( 861 'uri' => 'http://localhost/oneuri', 862 'redirect' => 1 863 ); 864 $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/oneruri\r\n\r\n"; 865 $serverResponse2 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; 866 $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1)); 867 $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2)); 868 869 $response = $this->Socket->request($request); 870 $this->assertEquals(0, $this->Socket->request['redirect']); 871 $this->assertEquals(302, $response->code); 872 $this->assertEquals('http://localhost/anotheruri', $response->getHeader('Location')); 873 } 874 875/** 876 * testProxy method 877 * 878 * @return void 879 */ 880 public function testProxy() { 881 $this->Socket->reset(); 882 $this->Socket->expects($this->any())->method('connect')->will($this->returnValue(true)); 883 $this->Socket->expects($this->any())->method('read')->will($this->returnValue(false)); 884 885 $this->Socket->configProxy('proxy.server', 123); 886 $expected = "GET http://www.cakephp.org/ HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"; 887 $this->Socket->request('http://www.cakephp.org/'); 888 $this->assertEquals($expected, $this->Socket->request['raw']); 889 $this->assertEquals('proxy.server', $this->Socket->config['host']); 890 $this->assertEquals(123, $this->Socket->config['port']); 891 $expected = array( 892 'host' => 'proxy.server', 893 'port' => 123, 894 'method' => null, 895 'user' => null, 896 'pass' => null 897 ); 898 $this->assertEquals($expected, $this->Socket->request['proxy']); 899 900 $expected = "GET http://www.cakephp.org/bakery HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"; 901 $this->Socket->request('/bakery'); 902 $this->assertEquals($expected, $this->Socket->request['raw']); 903 $this->assertEquals('proxy.server', $this->Socket->config['host']); 904 $this->assertEquals(123, $this->Socket->config['port']); 905 $expected = array( 906 'host' => 'proxy.server', 907 'port' => 123, 908 'method' => null, 909 'user' => null, 910 'pass' => null 911 ); 912 $this->assertEquals($expected, $this->Socket->request['proxy']); 913 914 $expected = "GET http://www.cakephp.org/ HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nProxy-Authorization: Test mark.secret\r\n\r\n"; 915 $this->Socket->configProxy('proxy.server', 123, 'Test', 'mark', 'secret'); 916 $this->Socket->request('http://www.cakephp.org/'); 917 $this->assertEquals($expected, $this->Socket->request['raw']); 918 $this->assertEquals('proxy.server', $this->Socket->config['host']); 919 $this->assertEquals(123, $this->Socket->config['port']); 920 $expected = array( 921 'host' => 'proxy.server', 922 'port' => 123, 923 'method' => 'Test', 924 'user' => 'mark', 925 'pass' => 'secret' 926 ); 927 $this->assertEquals($expected, $this->Socket->request['proxy']); 928 929 $this->Socket->configAuth('Test', 'login', 'passwd'); 930 $expected = "GET http://www.cakephp.org/ HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nProxy-Authorization: Test mark.secret\r\nAuthorization: Test login.passwd\r\n\r\n"; 931 $this->Socket->request('http://www.cakephp.org/'); 932 $this->assertEquals($expected, $this->Socket->request['raw']); 933 $expected = array( 934 'host' => 'proxy.server', 935 'port' => 123, 936 'method' => 'Test', 937 'user' => 'mark', 938 'pass' => 'secret' 939 ); 940 $this->assertEquals($expected, $this->Socket->request['proxy']); 941 $expected = array( 942 'Test' => array( 943 'user' => 'login', 944 'pass' => 'passwd' 945 ) 946 ); 947 $this->assertEquals($expected, $this->Socket->request['auth']); 948 } 949 950/** 951 * testUrl method 952 * 953 * @return void 954 */ 955 public function testUrl() { 956 $this->Socket->reset(true); 957 958 $this->assertEquals(false, $this->Socket->url(true)); 959 960 $url = $this->Socket->url('www.cakephp.org'); 961 $this->assertEquals('http://www.cakephp.org/', $url); 962 963 $url = $this->Socket->url('https://www.cakephp.org/posts/add'); 964 $this->assertEquals('https://www.cakephp.org/posts/add', $url); 965 $url = $this->Socket->url('http://www.cakephp/search?q=socket', '/%path?%query'); 966 $this->assertEquals('/search?q=socket', $url); 967 968 $this->Socket->config['request']['uri']['host'] = 'bakery.cakephp.org'; 969 $url = $this->Socket->url(); 970 $this->assertEquals('http://bakery.cakephp.org/', $url); 971 972 $this->Socket->configUri('http://www.cakephp.org'); 973 $url = $this->Socket->url('/search?q=bar'); 974 $this->assertEquals('http://www.cakephp.org/search?q=bar', $url); 975 976 $url = $this->Socket->url(array('host' => 'www.foobar.org', 'query' => array('q' => 'bar'))); 977 $this->assertEquals('http://www.foobar.org/?q=bar', $url); 978 979 $url = $this->Socket->url(array('path' => '/supersearch', 'query' => array('q' => 'bar'))); 980 $this->assertEquals('http://www.cakephp.org/supersearch?q=bar', $url); 981 982 $this->Socket->configUri('http://www.google.com'); 983 $url = $this->Socket->url('/search?q=socket'); 984 $this->assertEquals('http://www.google.com/search?q=socket', $url); 985 986 $url = $this->Socket->url(); 987 $this->assertEquals('http://www.google.com/', $url); 988 989 $this->Socket->configUri('https://www.google.com'); 990 $url = $this->Socket->url('/search?q=socket'); 991 $this->assertEquals('https://www.google.com/search?q=socket', $url); 992 993 $this->Socket->reset(); 994 $this->Socket->configUri('www.google.com:443'); 995 $url = $this->Socket->url('/search?q=socket'); 996 $this->assertEquals('https://www.google.com/search?q=socket', $url); 997 998 $this->Socket->reset(); 999 $this->Socket->configUri('www.google.com:8080'); 1000 $url = $this->Socket->url('/search?q=socket'); 1001 $this->assertEquals('http://www.google.com:8080/search?q=socket', $url); 1002 } 1003 1004/** 1005 * testGet method 1006 * 1007 * @return void 1008 */ 1009 public function testGet() { 1010 $this->RequestSocket->reset(); 1011 1012 $this->RequestSocket->expects($this->at(0)) 1013 ->method('request') 1014 ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/')); 1015 1016 $this->RequestSocket->expects($this->at(1)) 1017 ->method('request') 1018 ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar')); 1019 1020 $this->RequestSocket->expects($this->at(2)) 1021 ->method('request') 1022 ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar')); 1023 1024 $this->RequestSocket->expects($this->at(3)) 1025 ->method('request') 1026 ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=23&foobar=42')); 1027 1028 $this->RequestSocket->expects($this->at(4)) 1029 ->method('request') 1030 ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/', 'version' => '1.0')); 1031 1032 $this->RequestSocket->expects($this->at(5)) 1033 ->method('request') 1034 ->with(array('method' => 'GET', 'uri' => 'https://secure.example.com/test.php?one=two')); 1035 1036 $this->RequestSocket->expects($this->at(6)) 1037 ->method('request') 1038 ->with(array('method' => 'GET', 'uri' => 'https://example.com/oauth/access?clientid=123&redirect_uri=http%3A%2F%2Fexample.com&code=456')); 1039 1040 $this->RequestSocket->get('http://www.google.com/'); 1041 $this->RequestSocket->get('http://www.google.com/', array('foo' => 'bar')); 1042 $this->RequestSocket->get('http://www.google.com/', 'foo=bar'); 1043 $this->RequestSocket->get('http://www.google.com/?foo=bar', array('foobar' => '42', 'foo' => '23')); 1044 $this->RequestSocket->get('http://www.google.com/', null, array('version' => '1.0')); 1045 $this->RequestSocket->get('https://secure.example.com/test.php', array('one' => 'two')); 1046 $this->RequestSocket->get('https://example.com/oauth/access', array( 1047 'clientid' => '123', 1048 'redirect_uri' => 'http://example.com', 1049 'code' => 456 1050 )); 1051 } 1052 1053/** 1054 * Test authentication 1055 * 1056 * @return void 1057 */ 1058 public function testAuth() { 1059 $socket = new MockHttpSocket(); 1060 $socket->get('http://mark:secret@example.com/test'); 1061 $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); 1062 1063 $socket->configAuth(false); 1064 $socket->get('http://example.com/test'); 1065 $this->assertFalse(strpos($socket->request['header'], 'Authorization:')); 1066 1067 $socket->configAuth('Test', 'mark', 'passwd'); 1068 $socket->get('http://example.com/test'); 1069 $this->assertTrue(strpos($socket->request['header'], 'Authorization: Test mark.passwd') !== false); 1070 1071 $socket->configAuth(false); 1072 $socket->request(array( 1073 'method' => 'GET', 1074 'uri' => 'http://example.com/test', 1075 'auth' => array( 1076 'method' => 'Basic', 1077 'user' => 'joel', 1078 'pass' => 'hunter2' 1079 ) 1080 )); 1081 $this->assertEquals($socket->request['auth'], array('Basic' => array('user' => 'joel', 'pass' => 'hunter2'))); 1082 $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic am9lbDpodW50ZXIy') !== false); 1083 } 1084 1085/** 1086 * test that two consecutive get() calls reset the authentication credentials. 1087 * 1088 * @return void 1089 */ 1090 public function testConsecutiveGetResetsAuthCredentials() { 1091 $socket = new MockHttpSocket(); 1092 $socket->get('http://mark:secret@example.com/test'); 1093 $this->assertEquals('mark', $socket->request['uri']['user']); 1094 $this->assertEquals('secret', $socket->request['uri']['pass']); 1095 $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); 1096 1097 $socket->get('/test2'); 1098 $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); 1099 1100 $socket->get('/test3'); 1101 $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); 1102 } 1103 1104/** 1105 * testPostPutDelete method 1106 * 1107 * @return void 1108 */ 1109 public function testPost() { 1110 $this->RequestSocket->reset(); 1111 $this->RequestSocket->expects($this->at(0)) 1112 ->method('request') 1113 ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => array())); 1114 1115 $this->RequestSocket->expects($this->at(1)) 1116 ->method('request') 1117 ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); 1118 1119 $this->RequestSocket->expects($this->at(2)) 1120 ->method('request') 1121 ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); 1122 1123 $this->RequestSocket->post('http://www.google.com/'); 1124 $this->RequestSocket->post('http://www.google.com/', array('Foo' => 'bar')); 1125 $this->RequestSocket->post('http://www.google.com/', null, array('line' => 'Hey Server')); 1126 } 1127 1128/** 1129 * testPut 1130 * 1131 * @return void 1132 */ 1133 public function testPut() { 1134 $this->RequestSocket->reset(); 1135 $this->RequestSocket->expects($this->at(0)) 1136 ->method('request') 1137 ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => array())); 1138 1139 $this->RequestSocket->expects($this->at(1)) 1140 ->method('request') 1141 ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); 1142 1143 $this->RequestSocket->expects($this->at(2)) 1144 ->method('request') 1145 ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); 1146 1147 $this->RequestSocket->put('http://www.google.com/'); 1148 $this->RequestSocket->put('http://www.google.com/', array('Foo' => 'bar')); 1149 $this->RequestSocket->put('http://www.google.com/', null, array('line' => 'Hey Server')); 1150 } 1151 1152/** 1153 * testPatch 1154 * 1155 * @return void 1156 */ 1157 public function testPatch() { 1158 $this->RequestSocket->reset(); 1159 $this->RequestSocket->expects($this->at(0)) 1160 ->method('request') 1161 ->with(array('method' => 'PATCH', 'uri' => 'http://www.google.com/', 'body' => array())); 1162 1163 $this->RequestSocket->expects($this->at(1)) 1164 ->method('request') 1165 ->with(array('method' => 'PATCH', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); 1166 1167 $this->RequestSocket->expects($this->at(2)) 1168 ->method('request') 1169 ->with(array('method' => 'PATCH', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); 1170 1171 $this->RequestSocket->patch('http://www.google.com/'); 1172 $this->RequestSocket->patch('http://www.google.com/', array('Foo' => 'bar')); 1173 $this->RequestSocket->patch('http://www.google.com/', null, array('line' => 'Hey Server')); 1174 } 1175 1176/** 1177 * testDelete 1178 * 1179 * @return void 1180 */ 1181 public function testDelete() { 1182 $this->RequestSocket->reset(); 1183 $this->RequestSocket->expects($this->at(0)) 1184 ->method('request') 1185 ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => array())); 1186 1187 $this->RequestSocket->expects($this->at(1)) 1188 ->method('request') 1189 ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); 1190 1191 $this->RequestSocket->expects($this->at(2)) 1192 ->method('request') 1193 ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); 1194 1195 $this->RequestSocket->delete('http://www.google.com/'); 1196 $this->RequestSocket->delete('http://www.google.com/', array('Foo' => 'bar')); 1197 $this->RequestSocket->delete('http://www.google.com/', null, array('line' => 'Hey Server')); 1198 } 1199 1200/** 1201 * testBuildRequestLine method 1202 * 1203 * @return void 1204 */ 1205 public function testBuildRequestLine() { 1206 $this->Socket->reset(); 1207 1208 $this->Socket->quirksMode = true; 1209 $r = $this->Socket->buildRequestLine('Foo'); 1210 $this->assertEquals('Foo', $r); 1211 $this->Socket->quirksMode = false; 1212 1213 $r = $this->Socket->buildRequestLine(true); 1214 $this->assertEquals(false, $r); 1215 1216 $r = $this->Socket->buildRequestLine(array('foo' => 'bar', 'method' => 'foo')); 1217 $this->assertEquals(false, $r); 1218 1219 $r = $this->Socket->buildRequestLine(array('method' => 'GET', 'uri' => 'http://www.cakephp.org/search?q=socket')); 1220 $this->assertEquals("GET /search?q=socket HTTP/1.1\r\n", $r); 1221 1222 $request = array( 1223 'method' => 'GET', 1224 'uri' => array( 1225 'path' => '/search', 1226 'query' => array('q' => 'socket') 1227 ) 1228 ); 1229 $r = $this->Socket->buildRequestLine($request); 1230 $this->assertEquals("GET /search?q=socket HTTP/1.1\r\n", $r); 1231 1232 unset($request['method']); 1233 $r = $this->Socket->buildRequestLine($request); 1234 $this->assertEquals("GET /search?q=socket HTTP/1.1\r\n", $r); 1235 1236 $r = $this->Socket->buildRequestLine($request, 'CAKE-HTTP/0.1'); 1237 $this->assertEquals("GET /search?q=socket CAKE-HTTP/0.1\r\n", $r); 1238 1239 $request = array('method' => 'OPTIONS', 'uri' => '*'); 1240 $r = $this->Socket->buildRequestLine($request); 1241 $this->assertEquals("OPTIONS * HTTP/1.1\r\n", $r); 1242 1243 $request['method'] = 'GET'; 1244 $this->Socket->quirksMode = true; 1245 $r = $this->Socket->buildRequestLine($request); 1246 $this->assertEquals("GET * HTTP/1.1\r\n", $r); 1247 1248 $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n"); 1249 $this->assertEquals("GET * HTTP/1.1\r\n", $r); 1250 } 1251 1252/** 1253 * testBadBuildRequestLine method 1254 * 1255 * @expectedException SocketException 1256 * @return void 1257 */ 1258 public function testBadBuildRequestLine() { 1259 $this->Socket->buildRequestLine('Foo'); 1260 } 1261 1262/** 1263 * testBadBuildRequestLine2 method 1264 * 1265 * @expectedException SocketException 1266 * @return void 1267 */ 1268 public function testBadBuildRequestLine2() { 1269 $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n"); 1270 } 1271 1272/** 1273 * Asserts that HttpSocket::parseUri is working properly 1274 * 1275 * @return void 1276 */ 1277 public function testParseUri() { 1278 $this->Socket->reset(); 1279 1280 $uri = $this->Socket->parseUri(array('invalid' => 'uri-string')); 1281 $this->assertEquals(false, $uri); 1282 1283 $uri = $this->Socket->parseUri(array('invalid' => 'uri-string'), array('host' => 'somehost')); 1284 $this->assertEquals(array('host' => 'somehost', 'invalid' => 'uri-string'), $uri); 1285 1286 $uri = $this->Socket->parseUri(false); 1287 $this->assertEquals(false, $uri); 1288 1289 $uri = $this->Socket->parseUri('/my-cool-path'); 1290 $this->assertEquals(array('path' => '/my-cool-path'), $uri); 1291 1292 $uri = $this->Socket->parseUri('http://bob:foo123@www.cakephp.org:40/search?q=dessert#results'); 1293 $this->assertEquals($uri, array( 1294 'scheme' => 'http', 1295 'host' => 'www.cakephp.org', 1296 'port' => 40, 1297 'user' => 'bob', 1298 'pass' => 'foo123', 1299 'path' => '/search', 1300 'query' => array('q' => 'dessert'), 1301 'fragment' => 'results' 1302 )); 1303 1304 $uri = $this->Socket->parseUri('http://www.cakephp.org/'); 1305 $this->assertEquals($uri, array( 1306 'scheme' => 'http', 1307 'host' => 'www.cakephp.org', 1308 'path' => '/' 1309 )); 1310 1311 $uri = $this->Socket->parseUri('http://www.cakephp.org', true); 1312 $this->assertEquals($uri, array( 1313 'scheme' => 'http', 1314 'host' => 'www.cakephp.org', 1315 'port' => 80, 1316 'user' => null, 1317 'pass' => null, 1318 'path' => '/', 1319 'query' => array(), 1320 'fragment' => null 1321 )); 1322 1323 $uri = $this->Socket->parseUri('https://www.cakephp.org', true); 1324 $this->assertEquals($uri, array( 1325 'scheme' => 'https', 1326 'host' => 'www.cakephp.org', 1327 'port' => 443, 1328 'user' => null, 1329 'pass' => null, 1330 'path' => '/', 1331 'query' => array(), 1332 'fragment' => null 1333 )); 1334 1335 $uri = $this->Socket->parseUri('www.cakephp.org:443/query?foo', true); 1336 $this->assertEquals($uri, array( 1337 'scheme' => 'https', 1338 'host' => 'www.cakephp.org', 1339 'port' => 443, 1340 'user' => null, 1341 'pass' => null, 1342 'path' => '/query', 1343 'query' => array('foo' => ""), 1344 'fragment' => null 1345 )); 1346 1347 $uri = $this->Socket->parseUri('http://www.cakephp.org', array('host' => 'piephp.org', 'user' => 'bob', 'fragment' => 'results')); 1348 $this->assertEquals($uri, array( 1349 'host' => 'www.cakephp.org', 1350 'user' => 'bob', 1351 'fragment' => 'results', 1352 'scheme' => 'http' 1353 )); 1354 1355 $uri = $this->Socket->parseUri('https://www.cakephp.org', array('scheme' => 'http', 'port' => 23)); 1356 $this->assertEquals($uri, array( 1357 'scheme' => 'https', 1358 'port' => 23, 1359 'host' => 'www.cakephp.org' 1360 )); 1361 1362 $uri = $this->Socket->parseUri('www.cakephp.org:59', array('scheme' => array('http', 'https'), 'port' => 80)); 1363 $this->assertEquals($uri, array( 1364 'scheme' => 'http', 1365 'port' => 59, 1366 'host' => 'www.cakephp.org' 1367 )); 1368 1369 $uri = $this->Socket->parseUri(array('scheme' => 'http', 'host' => 'www.google.com', 'port' => 8080), array('scheme' => array('http', 'https'), 'host' => 'www.google.com', 'port' => array(80, 443))); 1370 $this->assertEquals($uri, array( 1371 'scheme' => 'http', 1372 'host' => 'www.google.com', 1373 'port' => 8080 1374 )); 1375 1376 $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1¶m2=value2%3Dvalue3'); 1377 $this->assertEquals($uri, array( 1378 'scheme' => 'http', 1379 'host' => 'www.cakephp.org', 1380 'path' => '/', 1381 'query' => array( 1382 'param1' => 'value1', 1383 'param2' => 'value2=value3' 1384 ) 1385 )); 1386 1387 $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1¶m2=value2=value3'); 1388 $this->assertEquals($uri, array( 1389 'scheme' => 'http', 1390 'host' => 'www.cakephp.org', 1391 'path' => '/', 1392 'query' => array( 1393 'param1' => 'value1', 1394 'param2' => 'value2=value3' 1395 ) 1396 )); 1397 } 1398 1399/** 1400 * Tests that HttpSocket::buildUri can turn all kinds of uri arrays (and strings) into fully or partially qualified URI's 1401 * 1402 * @return void 1403 */ 1404 public function testBuildUri() { 1405 $this->Socket->reset(); 1406 1407 $r = $this->Socket->buildUri(true); 1408 $this->assertEquals(false, $r); 1409 1410 $r = $this->Socket->buildUri('foo.com'); 1411 $this->assertEquals('http://foo.com/', $r); 1412 1413 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org')); 1414 $this->assertEquals('http://www.cakephp.org/', $r); 1415 1416 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https')); 1417 $this->assertEquals('https://www.cakephp.org/', $r); 1418 1419 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'port' => 23)); 1420 $this->assertEquals('http://www.cakephp.org:23/', $r); 1421 1422 $r = $this->Socket->buildUri(array('path' => 'www.google.com/search', 'query' => 'q=cakephp')); 1423 $this->assertEquals('http://www.google.com/search?q=cakephp', $r); 1424 1425 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https', 'port' => 79)); 1426 $this->assertEquals('https://www.cakephp.org:79/', $r); 1427 1428 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => 'foo')); 1429 $this->assertEquals('http://www.cakephp.org/foo', $r); 1430 1431 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/foo')); 1432 $this->assertEquals('http://www.cakephp.org/foo', $r); 1433 1434 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/search', 'query' => array('q' => 'HttpSocket'))); 1435 $this->assertEquals('http://www.cakephp.org/search?q=HttpSocket', $r); 1436 1437 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar')); 1438 $this->assertEquals('http://www.cakephp.org/#bar', $r); 1439 1440 $r = $this->Socket->buildUri(array( 1441 'scheme' => 'https', 1442 'host' => 'www.cakephp.org', 1443 'port' => 25, 1444 'user' => 'bob', 1445 'pass' => 'secret', 1446 'path' => '/cool', 1447 'query' => array('foo' => 'bar'), 1448 'fragment' => 'comment' 1449 )); 1450 $this->assertEquals('https://bob:secret@www.cakephp.org:25/cool?foo=bar#comment', $r); 1451 1452 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar'), '%fragment?%host'); 1453 $this->assertEquals('bar?www.cakephp.org', $r); 1454 1455 $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org'), '%fragment???%host'); 1456 $this->assertEquals('???www.cakephp.org', $r); 1457 1458 $r = $this->Socket->buildUri(array('path' => '*'), '/%path?%query'); 1459 $this->assertEquals('*', $r); 1460 1461 $r = $this->Socket->buildUri(array('scheme' => 'foo', 'host' => 'www.cakephp.org')); 1462 $this->assertEquals('foo://www.cakephp.org:80/', $r); 1463 } 1464 1465/** 1466 * Asserts that HttpSocket::parseQuery is working properly 1467 * 1468 * @return void 1469 */ 1470 public function testParseQuery() { 1471 $this->Socket->reset(); 1472 1473 $query = $this->Socket->parseQuery(array('framework' => 'cakephp')); 1474 $this->assertEquals(array('framework' => 'cakephp'), $query); 1475 1476 $query = $this->Socket->parseQuery(''); 1477 $this->assertEquals(array(), $query); 1478 1479 $query = $this->Socket->parseQuery('framework=cakephp'); 1480 $this->assertEquals(array('framework' => 'cakephp'), $query); 1481 1482 $query = $this->Socket->parseQuery('?framework=cakephp'); 1483 $this->assertEquals(array('framework' => 'cakephp'), $query); 1484 1485 $query = $this->Socket->parseQuery('a&b&c'); 1486 $this->assertEquals(array('a' => '', 'b' => '', 'c' => ''), $query); 1487 1488 $query = $this->Socket->parseQuery('value=12345'); 1489 $this->assertEquals(array('value' => '12345'), $query); 1490 1491 $query = $this->Socket->parseQuery('a[0]=foo&a[1]=bar&a[2]=cake'); 1492 $this->assertEquals(array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')), $query); 1493 1494 $query = $this->Socket->parseQuery('a[]=foo&a[]=bar&a[]=cake'); 1495 $this->assertEquals(array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')), $query); 1496 1497 $query = $this->Socket->parseQuery('a[][]=foo&a[][]=bar&a[][]=cake'); 1498 $expectedQuery = array( 1499 'a' => array( 1500 0 => array( 1501 0 => 'foo' 1502 ), 1503 1 => array( 1504 0 => 'bar' 1505 ), 1506 array( 1507 0 => 'cake' 1508 ) 1509 ) 1510 ); 1511 $this->assertEquals($expectedQuery, $query); 1512 1513 $query = $this->Socket->parseQuery('a[][]=foo&a[bar]=php&a[][]=bar&a[][]=cake'); 1514 $expectedQuery = array( 1515 'a' => array( 1516 array('foo'), 1517 'bar' => 'php', 1518 array('bar'), 1519 array('cake') 1520 ) 1521 ); 1522 $this->assertEquals($expectedQuery, $query); 1523 1524 $query = $this->Socket->parseQuery('user[]=jim&user[3]=tom&user[]=bob'); 1525 $expectedQuery = array( 1526 'user' => array( 1527 0 => 'jim', 1528 3 => 'tom', 1529 4 => 'bob' 1530 ) 1531 ); 1532 $this->assertEquals($expectedQuery, $query); 1533 1534 $queryStr = 'user[0]=foo&user[0][items][]=foo&user[0][items][]=bar&user[][name]=jim&user[1][items][personal][]=book&user[1][items][personal][]=pen&user[1][items][]=ball&user[count]=2&empty'; 1535 $query = $this->Socket->parseQuery($queryStr); 1536 $expectedQuery = array( 1537 'user' => array( 1538 0 => array( 1539 'items' => array( 1540 'foo', 1541 'bar' 1542 ) 1543 ), 1544 1 => array( 1545 'name' => 'jim', 1546 'items' => array( 1547 'personal' => array( 1548 'book', 1549 'pen' 1550 ), 1551 'ball' 1552 ) 1553 ), 1554 'count' => '2' 1555 ), 1556 'empty' => '' 1557 ); 1558 $this->assertEquals($expectedQuery, $query); 1559 1560 $query = 'openid.ns=example.com&foo=bar&foo=baz'; 1561 $result = $this->Socket->parseQuery($query); 1562 $expected = array( 1563 'openid.ns' => 'example.com', 1564 'foo' => array('bar', 'baz') 1565 ); 1566 $this->assertEquals($expected, $result); 1567 } 1568 1569/** 1570 * Tests that HttpSocket::buildHeader can turn a given $header array into a proper header string according to 1571 * HTTP 1.1 specs. 1572 * 1573 * @return void 1574 */ 1575 public function testBuildHeader() { 1576 $this->Socket->reset(); 1577 1578 $r = $this->Socket->buildHeader(true); 1579 $this->assertEquals(false, $r); 1580 1581 $r = $this->Socket->buildHeader('My raw header'); 1582 $this->assertEquals('My raw header', $r); 1583 1584 $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org')); 1585 $this->assertEquals("Host: www.cakephp.org\r\n", $r); 1586 1587 $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org', 'Connection' => 'Close')); 1588 $this->assertEquals("Host: www.cakephp.org\r\nConnection: Close\r\n", $r); 1589 1590 $r = $this->Socket->buildHeader(array('People' => array('Bob', 'Jim', 'John'))); 1591 $this->assertEquals("People: Bob,Jim,John\r\n", $r); 1592 1593 $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\nMulti Line field")); 1594 $this->assertEquals("Multi-Line-Field: This is my\r\n Multi Line field\r\n", $r); 1595 1596 $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n Multi Line field")); 1597 $this->assertEquals("Multi-Line-Field: This is my\r\n Multi Line field\r\n", $r); 1598 1599 $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n\tMulti Line field")); 1600 $this->assertEquals("Multi-Line-Field: This is my\r\n\tMulti Line field\r\n", $r); 1601 1602 $r = $this->Socket->buildHeader(array('Test@Field' => "My value")); 1603 $this->assertEquals("Test\"@\"Field: My value\r\n", $r); 1604 } 1605 1606/** 1607 * testBuildCookies method 1608 * 1609 * @return void 1610 */ 1611 public function testBuildCookies() { 1612 $cookies = array( 1613 'foo' => array( 1614 'value' => 'bar' 1615 ), 1616 'people' => array( 1617 'value' => 'jim,jack,johnny;', 1618 'path' => '/accounts' 1619 ), 1620 'key' => 'value' 1621 ); 1622 $expect = "Cookie: foo=bar; people=jim,jack,johnny\";\"; key=value\r\n"; 1623 $result = $this->Socket->buildCookies($cookies); 1624 $this->assertEquals($expect, $result); 1625 } 1626 1627/** 1628 * Tests that HttpSocket::_tokenEscapeChars() returns the right characters. 1629 * 1630 * @return void 1631 */ 1632 public function testTokenEscapeChars() { 1633 $this->Socket->reset(); 1634 1635 $expected = array( 1636 '\x22', '\x28', '\x29', '\x3c', '\x3e', '\x40', '\x2c', '\x3b', '\x3a', '\x5c', '\x2f', '\x5b', '\x5d', '\x3f', '\x3d', '\x7b', 1637 '\x7d', '\x20', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', 1638 '\x0e', '\x0f', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', 1639 '\x1e', '\x1f', '\x7f' 1640 ); 1641 $r = $this->Socket->tokenEscapeChars(); 1642 $this->assertEquals($expected, $r); 1643 1644 foreach ($expected as $key => $char) { 1645 $expected[$key] = chr(hexdec(substr($char, 2))); 1646 } 1647 1648 $r = $this->Socket->tokenEscapeChars(false); 1649 $this->assertEquals($expected, $r); 1650 } 1651 1652/** 1653 * Test that HttpSocket::escapeToken is escaping all characters as described in RFC 2616 (HTTP 1.1 specs) 1654 * 1655 * @return void 1656 */ 1657 public function testEscapeToken() { 1658 $this->Socket->reset(); 1659 1660 $this->assertEquals('Foo', $this->Socket->escapeToken('Foo')); 1661 1662 $escape = $this->Socket->tokenEscapeChars(false); 1663 foreach ($escape as $char) { 1664 $token = 'My-special-' . $char . '-Token'; 1665 $escapedToken = $this->Socket->escapeToken($token); 1666 $expectedToken = 'My-special-"' . $char . '"-Token'; 1667 1668 $this->assertEquals($expectedToken, $escapedToken, 'Test token escaping for ASCII ' . ord($char)); 1669 } 1670 1671 $token = 'Extreme-:Token- -"@-test'; 1672 $escapedToken = $this->Socket->escapeToken($token); 1673 $expectedToken = 'Extreme-":"Token-" "-""""@"-test'; 1674 $this->assertEquals($expectedToken, $escapedToken); 1675 } 1676 1677/** 1678 * This tests asserts HttpSocket::reset() resets a HttpSocket instance to it's initial state (before Object::__construct 1679 * got executed) 1680 * 1681 * @return void 1682 */ 1683 public function testReset() { 1684 $this->Socket->reset(); 1685 1686 $initialState = get_class_vars('HttpSocket'); 1687 foreach ($initialState as $property => $value) { 1688 $this->Socket->{$property} = 'Overwritten'; 1689 } 1690 1691 $return = $this->Socket->reset(); 1692 1693 foreach ($initialState as $property => $value) { 1694 $this->assertEquals($this->Socket->{$property}, $value); 1695 } 1696 1697 $this->assertEquals(true, $return); 1698 } 1699 1700/** 1701 * This tests asserts HttpSocket::reset(false) resets certain HttpSocket properties to their initial state (before 1702 * Object::__construct got executed). 1703 * 1704 * @return void 1705 */ 1706 public function testPartialReset() { 1707 $this->Socket->reset(); 1708 1709 $partialResetProperties = array('request', 'response'); 1710 $initialState = get_class_vars('HttpSocket'); 1711 1712 foreach ($initialState as $property => $value) { 1713 $this->Socket->{$property} = 'Overwritten'; 1714 } 1715 1716 $return = $this->Socket->reset(false); 1717 1718 foreach ($initialState as $property => $originalValue) { 1719 if (in_array($property, $partialResetProperties)) { 1720 $this->assertEquals($this->Socket->{$property}, $originalValue); 1721 } else { 1722 $this->assertEquals('Overwritten', $this->Socket->{$property}); 1723 } 1724 } 1725 $this->assertEquals(true, $return); 1726 } 1727 1728/** 1729 * test configuring the context from the flat keys. 1730 * 1731 * @return void 1732 */ 1733 public function testConfigContext() { 1734 $this->Socket->reset(); 1735 $this->Socket->request('http://example.com'); 1736 $this->assertTrue($this->Socket->config['context']['ssl']['verify_peer']); 1737 $this->assertFalse($this->Socket->config['context']['ssl']['allow_self_signed']); 1738 $this->assertEquals(5, $this->Socket->config['context']['ssl']['verify_depth']); 1739 $this->assertEquals('example.com', $this->Socket->config['context']['ssl']['CN_match']); 1740 $this->assertArrayNotHasKey('ssl_verify_peer', $this->Socket->config); 1741 $this->assertArrayNotHasKey('ssl_allow_self_signed', $this->Socket->config); 1742 $this->assertArrayNotHasKey('ssl_verify_host', $this->Socket->config); 1743 $this->assertArrayNotHasKey('ssl_verify_depth', $this->Socket->config); 1744 } 1745 1746/** 1747 * Test that requests fail when peer verification fails. 1748 * 1749 * @return void 1750 */ 1751 public function testVerifyPeer() { 1752 $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); 1753 $socket = new HttpSocket(); 1754 try { 1755 $socket->get('https://typography.com'); 1756 $this->markTestSkipped('Found valid certificate, was expecting invalid certificate.'); 1757 } catch (SocketException $e) { 1758 $message = $e->getMessage(); 1759 $this->skipIf(strpos($message, 'Invalid HTTP') !== false, 'Invalid HTTP Response received, skipping.'); 1760 $this->assertContains('Peer certificate CN', $message); 1761 $this->assertContains('Failed to enable crypto', $message); 1762 } 1763 } 1764}