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