PageRenderTime 75ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/tirecore/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php

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