HttpSocketTest.php 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607
  1. <?php
  2. /**
  3. * HttpSocketTest file
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
  8. * Copyright 2005-2011, 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-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://book.cakephp.org/view/1196/Testing 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 mixed $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 $uri URI to parse
  86. * @param mixed $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 formated 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 mixed $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['protocol'] = getprotobyname($baseConfig['protocol']);
  207. $this->assertEquals($this->Socket->config, $baseConfig);
  208. $this->Socket->reset();
  209. $this->Socket->__construct(array('request' => array('uri' => 'http://www.cakephp.org:23/')));
  210. $this->assertEquals($this->Socket->config, $baseConfig);
  211. }
  212. /**
  213. * Test that HttpSocket::configUri works properly with different types of arguments
  214. *
  215. * @return void
  216. */
  217. public function testConfigUri() {
  218. $this->Socket->reset();
  219. $r = $this->Socket->configUri('https://bob:secret@www.cakephp.org:23/?query=foo');
  220. $expected = array(
  221. 'persistent' => false,
  222. 'host' => 'www.cakephp.org',
  223. 'protocol' => 'tcp',
  224. 'port' => 23,
  225. 'timeout' => 30,
  226. 'request' => array(
  227. 'uri' => array(
  228. 'scheme' => 'https',
  229. 'host' => 'www.cakephp.org',
  230. 'port' => 23
  231. ),
  232. 'redirect' => false,
  233. 'cookies' => array()
  234. )
  235. );
  236. $this->assertEquals($this->Socket->config, $expected);
  237. $this->assertTrue($r);
  238. $r = $this->Socket->configUri(array('host' => 'www.foo-bar.org'));
  239. $expected['host'] = 'www.foo-bar.org';
  240. $expected['request']['uri']['host'] = 'www.foo-bar.org';
  241. $this->assertEquals($this->Socket->config, $expected);
  242. $this->assertTrue($r);
  243. $r = $this->Socket->configUri('http://www.foo.com');
  244. $expected = array(
  245. 'persistent' => false,
  246. 'host' => 'www.foo.com',
  247. 'protocol' => 'tcp',
  248. 'port' => 80,
  249. 'timeout' => 30,
  250. 'request' => array(
  251. 'uri' => array(
  252. 'scheme' => 'http',
  253. 'host' => 'www.foo.com',
  254. 'port' => 80
  255. ),
  256. 'redirect' => false,
  257. 'cookies' => array()
  258. )
  259. );
  260. $this->assertEquals($this->Socket->config, $expected);
  261. $this->assertTrue($r);
  262. $r = $this->Socket->configUri('/this-is-broken');
  263. $this->assertEquals($this->Socket->config, $expected);
  264. $this->assertFalse($r);
  265. $r = $this->Socket->configUri(false);
  266. $this->assertEquals($this->Socket->config, $expected);
  267. $this->assertFalse($r);
  268. }
  269. /**
  270. * Tests that HttpSocket::request (the heart of the HttpSocket) is working properly.
  271. *
  272. * @return void
  273. */
  274. public function testRequest() {
  275. $this->Socket->reset();
  276. $response = $this->Socket->request(true);
  277. $this->assertFalse($response);
  278. $tests = array(
  279. array(
  280. 'request' => 'http://www.cakephp.org/?foo=bar',
  281. 'expectation' => array(
  282. 'config' => array(
  283. 'persistent' => false,
  284. 'host' => 'www.cakephp.org',
  285. 'protocol' => 'tcp',
  286. 'port' => 80,
  287. 'timeout' => 30,
  288. 'request' => array(
  289. 'uri' => array(
  290. 'scheme' => 'http',
  291. 'host' => 'www.cakephp.org',
  292. 'port' => 80
  293. ),
  294. 'redirect' => false,
  295. 'cookies' => array()
  296. )
  297. ),
  298. 'request' => array(
  299. 'method' => 'GET',
  300. 'uri' => array(
  301. 'scheme' => 'http',
  302. 'host' => 'www.cakephp.org',
  303. 'port' => 80,
  304. 'user' => null,
  305. 'pass' => null,
  306. 'path' => '/',
  307. 'query' => array('foo' => 'bar'),
  308. 'fragment' => null
  309. ),
  310. 'version' => '1.1',
  311. 'body' => '',
  312. 'line' => "GET /?foo=bar HTTP/1.1\r\n",
  313. 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n",
  314. 'raw' => "",
  315. 'redirect' => false,
  316. 'cookies' => array(),
  317. 'proxy' => array(),
  318. 'auth' => array()
  319. )
  320. )
  321. ),
  322. array(
  323. 'request' => array(
  324. 'uri' => array(
  325. 'host' => 'www.cakephp.org',
  326. 'query' => '?foo=bar'
  327. )
  328. )
  329. ),
  330. array(
  331. 'request' => 'www.cakephp.org/?foo=bar'
  332. ),
  333. array(
  334. 'request' => array(
  335. 'host' => '192.168.0.1',
  336. 'uri' => 'http://www.cakephp.org/?foo=bar'
  337. ),
  338. 'expectation' => array(
  339. 'request' => array(
  340. 'uri' => array('host' => 'www.cakephp.org')
  341. ),
  342. 'config' => array(
  343. 'request' => array(
  344. 'uri' => array('host' => 'www.cakephp.org')
  345. ),
  346. 'host' => '192.168.0.1'
  347. )
  348. )
  349. ),
  350. 'reset4' => array(
  351. 'request.uri.query' => array()
  352. ),
  353. array(
  354. 'request' => array(
  355. 'header' => array('Foo@woo' => 'bar-value')
  356. ),
  357. 'expectation' => array(
  358. 'request' => array(
  359. 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n",
  360. 'line' => "GET / HTTP/1.1\r\n"
  361. )
  362. )
  363. ),
  364. array(
  365. 'request' => array('header' => array('Foo@woo' => 'bar-value', 'host' => 'foo.com'), 'uri' => 'http://www.cakephp.org/'),
  366. 'expectation' => array(
  367. 'request' => array(
  368. 'header' => "Host: foo.com\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n"
  369. ),
  370. 'config' => array(
  371. 'host' => 'www.cakephp.org'
  372. )
  373. )
  374. ),
  375. array(
  376. 'request' => array('header' => "Foo: bar\r\n"),
  377. 'expectation' => array(
  378. 'request' => array(
  379. 'header' => "Foo: bar\r\n"
  380. )
  381. )
  382. ),
  383. array(
  384. 'request' => array('header' => "Foo: bar\r\n", 'uri' => 'http://www.cakephp.org/search?q=http_socket#ignore-me'),
  385. 'expectation' => array(
  386. 'request' => array(
  387. 'uri' => array(
  388. 'path' => '/search',
  389. 'query' => array('q' => 'http_socket'),
  390. 'fragment' => 'ignore-me'
  391. ),
  392. 'line' => "GET /search?q=http_socket HTTP/1.1\r\n"
  393. )
  394. )
  395. ),
  396. 'reset8' => array(
  397. 'request.uri.query' => array()
  398. ),
  399. array(
  400. 'request' => array(
  401. 'method' => 'POST',
  402. 'uri' => 'http://www.cakephp.org/posts/add',
  403. 'body' => array(
  404. 'name' => 'HttpSocket-is-released',
  405. 'date' => 'today'
  406. )
  407. ),
  408. 'expectation' => array(
  409. 'request' => array(
  410. 'method' => 'POST',
  411. 'uri' => array(
  412. 'path' => '/posts/add',
  413. 'fragment' => null
  414. ),
  415. 'body' => "name=HttpSocket-is-released&date=today",
  416. 'line' => "POST /posts/add HTTP/1.1\r\n",
  417. '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",
  418. 'raw' => "name=HttpSocket-is-released&date=today"
  419. )
  420. )
  421. ),
  422. array(
  423. 'request' => array(
  424. 'method' => 'POST',
  425. 'uri' => 'http://www.cakephp.org:8080/posts/add',
  426. 'body' => array(
  427. 'name' => 'HttpSocket-is-released',
  428. 'date' => 'today'
  429. )
  430. ),
  431. 'expectation' => array(
  432. 'config' => array(
  433. 'port' => 8080,
  434. 'request' => array(
  435. 'uri' => array(
  436. 'port' => 8080
  437. )
  438. )
  439. ),
  440. 'request' => array(
  441. 'uri' => array(
  442. 'port' => 8080
  443. ),
  444. '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"
  445. )
  446. )
  447. ),
  448. array(
  449. 'request' => array(
  450. 'method' => 'POST',
  451. 'uri' => 'https://www.cakephp.org/posts/add',
  452. 'body' => array(
  453. 'name' => 'HttpSocket-is-released',
  454. 'date' => 'today'
  455. )
  456. ),
  457. 'expectation' => array(
  458. 'config' => array(
  459. 'port' => 443,
  460. 'request' => array(
  461. 'uri' => array(
  462. 'scheme' => 'https',
  463. 'port' => 443
  464. )
  465. )
  466. ),
  467. 'request' => array(
  468. 'uri' => array(
  469. 'scheme' => 'https',
  470. 'port' => 443
  471. ),
  472. 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n"
  473. )
  474. )
  475. ),
  476. array(
  477. 'request' => array(
  478. 'method' => 'POST',
  479. 'uri' => 'https://www.cakephp.org/posts/add',
  480. 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'),
  481. 'cookies' => array('foo' => array('value' => 'bar'))
  482. ),
  483. 'expectation' => array(
  484. 'request' => array(
  485. '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",
  486. 'cookies' => array(
  487. 'foo' => array('value' => 'bar'),
  488. )
  489. )
  490. )
  491. )
  492. );
  493. $expectation = array();
  494. foreach ($tests as $i => $test) {
  495. if (strpos($i, 'reset') === 0) {
  496. foreach ($test as $path => $val) {
  497. $expectation = Set::insert($expectation, $path, $val);
  498. }
  499. continue;
  500. }
  501. if (isset($test['expectation'])) {
  502. $expectation = Set::merge($expectation, $test['expectation']);
  503. }
  504. $this->Socket->request($test['request']);
  505. $raw = $expectation['request']['raw'];
  506. $expectation['request']['raw'] = $expectation['request']['line'] . $expectation['request']['header'] . "\r\n" . $raw;
  507. $r = array('config' => $this->Socket->config, 'request' => $this->Socket->request);
  508. $v = $this->assertEquals($r, $expectation, 'Failed test #' . $i . ' ');
  509. $expectation['request']['raw'] = $raw;
  510. }
  511. $this->Socket->reset();
  512. $request = array('method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'));
  513. $response = $this->Socket->request($request);
  514. $this->assertEquals($this->Socket->request['body'], "name=HttpSocket-is-released&date=today");
  515. }
  516. /**
  517. * Test the scheme + port keys
  518. *
  519. * @return void
  520. */
  521. public function testGetWithSchemeAndPort() {
  522. $this->Socket->reset();
  523. $request = array(
  524. 'uri' => array(
  525. 'scheme' => 'http',
  526. 'host' => 'cakephp.org',
  527. 'port' => 8080,
  528. 'path' => '/',
  529. ),
  530. 'method' => 'GET'
  531. );
  532. $response = $this->Socket->request($request);
  533. $this->assertContains('Host: cakephp.org:8080', $this->Socket->request['header']);
  534. }
  535. /**
  536. * Test urls like http://cakephp.org/index.php?somestring without key/value pair for query
  537. *
  538. * @return void
  539. */
  540. public function testRequestWithStringQuery() {
  541. $this->Socket->reset();
  542. $request = array(
  543. 'uri' => array(
  544. 'scheme' => 'http',
  545. 'host' => 'cakephp.org',
  546. 'path' => 'index.php',
  547. 'query' => 'somestring'
  548. ),
  549. 'method' => 'GET'
  550. );
  551. $response = $this->Socket->request($request);
  552. $this->assertContains("GET /index.php?somestring HTTP/1.1", $this->Socket->request['line']);
  553. }
  554. /**
  555. * The "*" asterisk character is only allowed for the following methods: OPTIONS.
  556. *
  557. * @expectedException SocketException
  558. * @return void
  559. */
  560. public function testRequestNotAllowedUri() {
  561. $this->Socket->reset();
  562. $request = array('uri' => '*', 'method' => 'GET');
  563. $response = $this->Socket->request($request);
  564. }
  565. /**
  566. * testRequest2 method
  567. *
  568. * @return void
  569. */
  570. public function testRequest2() {
  571. $this->Socket->reset();
  572. $request = array('uri' => 'htpp://www.cakephp.org/');
  573. $number = mt_rand(0, 9999999);
  574. $this->Socket->expects($this->once())->method('connect')->will($this->returnValue(true));
  575. $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>";
  576. $this->Socket->expects($this->at(0))->method('read')->will($this->returnValue(false));
  577. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  578. $this->Socket->expects($this->once())->method('write')
  579. ->with("GET / HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n");
  580. $response = (string)$this->Socket->request($request);
  581. $this->assertEquals($response, "<h1>Hello, your lucky number is " . $number . "</h1>");
  582. }
  583. /**
  584. * testRequest3 method
  585. *
  586. * @return void
  587. */
  588. public function testRequest3() {
  589. $request = array('uri' => 'htpp://www.cakephp.org/');
  590. $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>";
  591. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  592. $this->Socket->connected = true;
  593. $this->Socket->request($request);
  594. $result = $this->Socket->response['cookies'];
  595. $expect = array(
  596. 'foo' => array(
  597. 'value' => 'bar'
  598. )
  599. );
  600. $this->assertEquals($result, $expect);
  601. $this->assertEquals($this->Socket->config['request']['cookies']['www.cakephp.org'], $expect);
  602. $this->assertFalse($this->Socket->connected);
  603. }
  604. /**
  605. * testRequestWithConstructor method
  606. *
  607. * @return void
  608. */
  609. public function testRequestWithConstructor() {
  610. $request = array(
  611. 'request' => array(
  612. 'uri' => array(
  613. 'scheme' => 'http',
  614. 'host' => 'localhost',
  615. 'port' => '5984',
  616. 'user' => null,
  617. 'pass' => null
  618. )
  619. )
  620. );
  621. $http = new MockHttpSocketRequests($request);
  622. $expected = array('method' => 'GET', 'uri' => '/_test');
  623. $http->expects($this->at(0))->method('request')->with($expected);
  624. $http->get('/_test');
  625. $expected = array('method' => 'GET', 'uri' => 'http://localhost:5984/_test?count=4');
  626. $http->expects($this->at(0))->method('request')->with($expected);
  627. $http->get('/_test', array('count' => 4));
  628. }
  629. /**
  630. * testRequestWithResource
  631. *
  632. * @return void
  633. */
  634. public function testRequestWithResource() {
  635. $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>";
  636. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  637. $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false));
  638. $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse));
  639. $this->Socket->connected = true;
  640. $f = fopen(TMP . 'download.txt', 'w');
  641. if (!$f) {
  642. $this->markTestSkipped('Can not write in TMP directory.');
  643. }
  644. $this->Socket->setContentResource($f);
  645. $result = (string)$this->Socket->request('http://www.cakephp.org/');
  646. $this->assertEquals($result, '');
  647. $this->assertEquals($this->Socket->response['header']['Server'], 'CakeHttp Server');
  648. fclose($f);
  649. $this->assertEquals(file_get_contents(TMP . 'download.txt'), '<h1>This is a test!</h1>');
  650. unlink(TMP . 'download.txt');
  651. $this->Socket->setContentResource(false);
  652. $result = (string)$this->Socket->request('http://www.cakephp.org/');
  653. $this->assertEquals($result, '<h1>This is a test!</h1>');
  654. }
  655. /**
  656. * testRequestWithCrossCookie
  657. *
  658. * @return void
  659. */
  660. public function testRequestWithCrossCookie() {
  661. $this->Socket->connected = true;
  662. $this->Socket->config['request']['cookies'] = array();
  663. $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>";
  664. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  665. $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false));
  666. $expected = array('www.cakephp.org' => array('foo' => array('value' => 'bar')));
  667. $this->Socket->request('http://www.cakephp.org/');
  668. $this->assertEquals($this->Socket->config['request']['cookies'], $expected);
  669. $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>";
  670. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  671. $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false));
  672. $this->Socket->request('http://www.cakephp.org/other');
  673. $this->assertEquals($this->Socket->request['cookies'], array('foo' => array('value' => 'bar')));
  674. $expected['www.cakephp.org'] += array('bar' => array('value' => 'foo'));
  675. $this->assertEquals($this->Socket->config['request']['cookies'], $expected);
  676. $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>";
  677. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  678. $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false));
  679. $this->Socket->request('/other2');
  680. $this->assertEquals($this->Socket->config['request']['cookies'], $expected);
  681. $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>";
  682. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  683. $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false));
  684. $this->Socket->request('http://www.cake.com');
  685. $this->assertTrue(empty($this->Socket->request['cookies']));
  686. $expected['www.cake.com'] = array('foobar' => array('value' => 'ok'));
  687. $this->assertEquals($this->Socket->config['request']['cookies'], $expected);
  688. }
  689. /**
  690. * testRequestCustomResponse
  691. *
  692. * @return void
  693. */
  694. public function testRequestCustomResponse() {
  695. $this->Socket->connected = true;
  696. $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>";
  697. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse));
  698. $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false));
  699. $this->Socket->responseClass = 'CustomResponse';
  700. $response = $this->Socket->request('http://www.cakephp.org/');
  701. $this->assertInstanceOf('CustomResponse', $response);
  702. $this->assertEquals($response->first10, 'HTTP/1.x 2');
  703. }
  704. /**
  705. * testRequestWithRedirect method
  706. *
  707. * @return void
  708. */
  709. public function testRequestWithRedirectAsTrue() {
  710. $request = array(
  711. 'uri' => 'http://localhost/oneuri',
  712. 'redirect' => true
  713. );
  714. $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";
  715. $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>";
  716. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1));
  717. $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2));
  718. $response = $this->Socket->request($request);
  719. $this->assertEquals('<h1>You have been redirected</h1>', $response->body());
  720. }
  721. public function testRequestWithRedirectAsInt() {
  722. $request = array(
  723. 'uri' => 'http://localhost/oneuri',
  724. 'redirect' => 2
  725. );
  726. $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";
  727. $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>";
  728. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1));
  729. $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2));
  730. $response = $this->Socket->request($request);
  731. $this->assertEquals(1, $this->Socket->request['redirect']);
  732. }
  733. public function testRequestWithRedirectAsIntReachingZero() {
  734. $request = array(
  735. 'uri' => 'http://localhost/oneuri',
  736. 'redirect' => 1
  737. );
  738. $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";
  739. $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";
  740. $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1));
  741. $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2));
  742. $response = $this->Socket->request($request);
  743. $this->assertEquals(0, $this->Socket->request['redirect']);
  744. $this->assertEquals(302, $response->code);
  745. $this->assertEquals('http://localhost/anotheruri', $response->getHeader('Location'));
  746. }
  747. /**
  748. * testProxy method
  749. *
  750. * @return void
  751. */
  752. public function testProxy() {
  753. $this->Socket->reset();
  754. $this->Socket->expects($this->any())->method('connect')->will($this->returnValue(true));
  755. $this->Socket->expects($this->any())->method('read')->will($this->returnValue(false));
  756. $this->Socket->configProxy('proxy.server', 123);
  757. $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";
  758. $this->Socket->request('http://www.cakephp.org/');
  759. $this->assertEquals($this->Socket->request['raw'], $expected);
  760. $this->assertEquals($this->Socket->config['host'], 'proxy.server');
  761. $this->assertEquals($this->Socket->config['port'], 123);
  762. $expected = array(
  763. 'host' => 'proxy.server',
  764. 'port' => 123,
  765. 'method' => null,
  766. 'user' => null,
  767. 'pass' => null
  768. );
  769. $this->assertEquals($this->Socket->request['proxy'], $expected);
  770. $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";
  771. $this->Socket->request('/bakery');
  772. $this->assertEquals($this->Socket->request['raw'], $expected);
  773. $this->assertEquals($this->Socket->config['host'], 'proxy.server');
  774. $this->assertEquals($this->Socket->config['port'], 123);
  775. $expected = array(
  776. 'host' => 'proxy.server',
  777. 'port' => 123,
  778. 'method' => null,
  779. 'user' => null,
  780. 'pass' => null
  781. );
  782. $this->assertEquals($this->Socket->request['proxy'], $expected);
  783. $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";
  784. $this->Socket->configProxy('proxy.server', 123, 'Test', 'mark', 'secret');
  785. $this->Socket->request('http://www.cakephp.org/');
  786. $this->assertEquals($this->Socket->request['raw'], $expected);
  787. $this->assertEquals($this->Socket->config['host'], 'proxy.server');
  788. $this->assertEquals($this->Socket->config['port'], 123);
  789. $expected = array(
  790. 'host' => 'proxy.server',
  791. 'port' => 123,
  792. 'method' => 'Test',
  793. 'user' => 'mark',
  794. 'pass' => 'secret'
  795. );
  796. $this->assertEquals($this->Socket->request['proxy'], $expected);
  797. $this->Socket->configAuth('Test', 'login', 'passwd');
  798. $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";
  799. $this->Socket->request('http://www.cakephp.org/');
  800. $this->assertEquals($this->Socket->request['raw'], $expected);
  801. $expected = array(
  802. 'host' => 'proxy.server',
  803. 'port' => 123,
  804. 'method' => 'Test',
  805. 'user' => 'mark',
  806. 'pass' => 'secret'
  807. );
  808. $this->assertEquals($this->Socket->request['proxy'], $expected);
  809. $expected = array(
  810. 'Test' => array(
  811. 'user' => 'login',
  812. 'pass' => 'passwd'
  813. )
  814. );
  815. $this->assertEquals($this->Socket->request['auth'], $expected);
  816. }
  817. /**
  818. * testUrl method
  819. *
  820. * @return void
  821. */
  822. public function testUrl() {
  823. $this->Socket->reset(true);
  824. $this->assertEquals($this->Socket->url(true), false);
  825. $url = $this->Socket->url('www.cakephp.org');
  826. $this->assertEquals($url, 'http://www.cakephp.org/');
  827. $url = $this->Socket->url('https://www.cakephp.org/posts/add');
  828. $this->assertEquals($url, 'https://www.cakephp.org/posts/add');
  829. $url = $this->Socket->url('http://www.cakephp/search?q=socket', '/%path?%query');
  830. $this->assertEquals($url, '/search?q=socket');
  831. $this->Socket->config['request']['uri']['host'] = 'bakery.cakephp.org';
  832. $url = $this->Socket->url();
  833. $this->assertEquals($url, 'http://bakery.cakephp.org/');
  834. $this->Socket->configUri('http://www.cakephp.org');
  835. $url = $this->Socket->url('/search?q=bar');
  836. $this->assertEquals($url, 'http://www.cakephp.org/search?q=bar');
  837. $url = $this->Socket->url(array('host' => 'www.foobar.org', 'query' => array('q' => 'bar')));
  838. $this->assertEquals($url, 'http://www.foobar.org/?q=bar');
  839. $url = $this->Socket->url(array('path' => '/supersearch', 'query' => array('q' => 'bar')));
  840. $this->assertEquals($url, 'http://www.cakephp.org/supersearch?q=bar');
  841. $this->Socket->configUri('http://www.google.com');
  842. $url = $this->Socket->url('/search?q=socket');
  843. $this->assertEquals($url, 'http://www.google.com/search?q=socket');
  844. $url = $this->Socket->url();
  845. $this->assertEquals($url, 'http://www.google.com/');
  846. $this->Socket->configUri('https://www.google.com');
  847. $url = $this->Socket->url('/search?q=socket');
  848. $this->assertEquals($url, 'https://www.google.com/search?q=socket');
  849. $this->Socket->reset();
  850. $this->Socket->configUri('www.google.com:443');
  851. $url = $this->Socket->url('/search?q=socket');
  852. $this->assertEquals($url, 'https://www.google.com/search?q=socket');
  853. $this->Socket->reset();
  854. $this->Socket->configUri('www.google.com:8080');
  855. $url = $this->Socket->url('/search?q=socket');
  856. $this->assertEquals($url, 'http://www.google.com:8080/search?q=socket');
  857. }
  858. /**
  859. * testGet method
  860. *
  861. * @return void
  862. */
  863. public function testGet() {
  864. $this->RequestSocket->reset();
  865. $this->RequestSocket->expects($this->at(0))
  866. ->method('request')
  867. ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/'));
  868. $this->RequestSocket->expects($this->at(1))
  869. ->method('request')
  870. ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar'));
  871. $this->RequestSocket->expects($this->at(2))
  872. ->method('request')
  873. ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar'));
  874. $this->RequestSocket->expects($this->at(3))
  875. ->method('request')
  876. ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=23&foobar=42'));
  877. $this->RequestSocket->expects($this->at(4))
  878. ->method('request')
  879. ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/', 'version' => '1.0'));
  880. $this->RequestSocket->get('http://www.google.com/');
  881. $this->RequestSocket->get('http://www.google.com/', array('foo' => 'bar'));
  882. $this->RequestSocket->get('http://www.google.com/', 'foo=bar');
  883. $this->RequestSocket->get('http://www.google.com/?foo=bar', array('foobar' => '42', 'foo' => '23'));
  884. $this->RequestSocket->get('http://www.google.com/', null, array('version' => '1.0'));
  885. }
  886. /**
  887. * Test authentication
  888. *
  889. * @return void
  890. */
  891. public function testAuth() {
  892. $socket = new MockHttpSocket();
  893. $socket->get('http://mark:secret@example.com/test');
  894. $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false);
  895. $socket->configAuth(false);
  896. $socket->get('http://example.com/test');
  897. $this->assertFalse(strpos($socket->request['header'], 'Authorization:'));
  898. $socket->configAuth('Test', 'mark', 'passwd');
  899. $socket->get('http://example.com/test');
  900. $this->assertTrue(strpos($socket->request['header'], 'Authorization: Test mark.passwd') !== false);
  901. }
  902. /**
  903. * test that two consecutive get() calls reset the authentication credentials.
  904. *
  905. * @return void
  906. */
  907. public function testConsecutiveGetResetsAuthCredentials() {
  908. $socket = new MockHttpSocket();
  909. $socket->get('http://mark:secret@example.com/test');
  910. $this->assertEquals($socket->request['uri']['user'], 'mark');
  911. $this->assertEquals($socket->request['uri']['pass'], 'secret');
  912. $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false);
  913. $socket->get('/test2');
  914. $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false);
  915. $socket->get('/test3');
  916. $this->assertTrue(strpos($socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false);
  917. }
  918. /**
  919. * testPostPutDelete method
  920. *
  921. * @return void
  922. */
  923. public function testPost() {
  924. $this->RequestSocket->reset();
  925. $this->RequestSocket->expects($this->at(0))
  926. ->method('request')
  927. ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => array()));
  928. $this->RequestSocket->expects($this->at(1))
  929. ->method('request')
  930. ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar')));
  931. $this->RequestSocket->expects($this->at(2))
  932. ->method('request')
  933. ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server'));
  934. $this->RequestSocket->post('http://www.google.com/');
  935. $this->RequestSocket->post('http://www.google.com/', array('Foo' => 'bar'));
  936. $this->RequestSocket->post('http://www.google.com/', null, array('line' => 'Hey Server'));
  937. }
  938. /**
  939. * testPut
  940. *
  941. * @return void
  942. */
  943. public function testPut() {
  944. $this->RequestSocket->reset();
  945. $this->RequestSocket->expects($this->at(0))
  946. ->method('request')
  947. ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => array()));
  948. $this->RequestSocket->expects($this->at(1))
  949. ->method('request')
  950. ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar')));
  951. $this->RequestSocket->expects($this->at(2))
  952. ->method('request')
  953. ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server'));
  954. $this->RequestSocket->put('http://www.google.com/');
  955. $this->RequestSocket->put('http://www.google.com/', array('Foo' => 'bar'));
  956. $this->RequestSocket->put('http://www.google.com/', null, array('line' => 'Hey Server'));
  957. }
  958. /**
  959. * testDelete
  960. *
  961. * @return void
  962. */
  963. public function testDelete() {
  964. $this->RequestSocket->reset();
  965. $this->RequestSocket->expects($this->at(0))
  966. ->method('request')
  967. ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => array()));
  968. $this->RequestSocket->expects($this->at(1))
  969. ->method('request')
  970. ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar')));
  971. $this->RequestSocket->expects($this->at(2))
  972. ->method('request')
  973. ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server'));
  974. $this->RequestSocket->delete('http://www.google.com/');
  975. $this->RequestSocket->delete('http://www.google.com/', array('Foo' => 'bar'));
  976. $this->RequestSocket->delete('http://www.google.com/', null, array('line' => 'Hey Server'));
  977. }
  978. /**
  979. * testBuildRequestLine method
  980. *
  981. * @return void
  982. */
  983. public function testBuildRequestLine() {
  984. $this->Socket->reset();
  985. $this->Socket->quirksMode = true;
  986. $r = $this->Socket->buildRequestLine('Foo');
  987. $this->assertEquals($r, 'Foo');
  988. $this->Socket->quirksMode = false;
  989. $r = $this->Socket->buildRequestLine(true);
  990. $this->assertEquals($r, false);
  991. $r = $this->Socket->buildRequestLine(array('foo' => 'bar', 'method' => 'foo'));
  992. $this->assertEquals($r, false);
  993. $r = $this->Socket->buildRequestLine(array('method' => 'GET', 'uri' => 'http://www.cakephp.org/search?q=socket'));
  994. $this->assertEquals($r, "GET /search?q=socket HTTP/1.1\r\n");
  995. $request = array(
  996. 'method' => 'GET',
  997. 'uri' => array(
  998. 'path' => '/search',
  999. 'query' => array('q' => 'socket')
  1000. )
  1001. );
  1002. $r = $this->Socket->buildRequestLine($request);
  1003. $this->assertEquals($r, "GET /search?q=socket HTTP/1.1\r\n");
  1004. unset($request['method']);
  1005. $r = $this->Socket->buildRequestLine($request);
  1006. $this->assertEquals($r, "GET /search?q=socket HTTP/1.1\r\n");
  1007. $r = $this->Socket->buildRequestLine($request, 'CAKE-HTTP/0.1');
  1008. $this->assertEquals($r, "GET /search?q=socket CAKE-HTTP/0.1\r\n");
  1009. $request = array('method' => 'OPTIONS', 'uri' => '*');
  1010. $r = $this->Socket->buildRequestLine($request);
  1011. $this->assertEquals($r, "OPTIONS * HTTP/1.1\r\n");
  1012. $request['method'] = 'GET';
  1013. $this->Socket->quirksMode = true;
  1014. $r = $this->Socket->buildRequestLine($request);
  1015. $this->assertEquals($r, "GET * HTTP/1.1\r\n");
  1016. $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n");
  1017. $this->assertEquals($r, "GET * HTTP/1.1\r\n");
  1018. }
  1019. /**
  1020. * testBadBuildRequestLine method
  1021. *
  1022. * @expectedException SocketException
  1023. * @return void
  1024. */
  1025. public function testBadBuildRequestLine() {
  1026. $r = $this->Socket->buildRequestLine('Foo');
  1027. }
  1028. /**
  1029. * testBadBuildRequestLine2 method
  1030. *
  1031. * @expectedException SocketException
  1032. * @return void
  1033. */
  1034. public function testBadBuildRequestLine2() {
  1035. $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n");
  1036. }
  1037. /**
  1038. * Asserts that HttpSocket::parseUri is working properly
  1039. *
  1040. * @return void
  1041. */
  1042. public function testParseUri() {
  1043. $this->Socket->reset();
  1044. $uri = $this->Socket->parseUri(array('invalid' => 'uri-string'));
  1045. $this->assertEquals($uri, false);
  1046. $uri = $this->Socket->parseUri(array('invalid' => 'uri-string'), array('host' => 'somehost'));
  1047. $this->assertEquals($uri, array('host' => 'somehost', 'invalid' => 'uri-string'));
  1048. $uri = $this->Socket->parseUri(false);
  1049. $this->assertEquals($uri, false);
  1050. $uri = $this->Socket->parseUri('/my-cool-path');
  1051. $this->assertEquals($uri, array('path' => '/my-cool-path'));
  1052. $uri = $this->Socket->parseUri('http://bob:foo123@www.cakephp.org:40/search?q=dessert#results');
  1053. $this->assertEquals($uri, array(
  1054. 'scheme' => 'http',
  1055. 'host' => 'www.cakephp.org',
  1056. 'port' => 40,
  1057. 'user' => 'bob',
  1058. 'pass' => 'foo123',
  1059. 'path' => '/search',
  1060. 'query' => array('q' => 'dessert'),
  1061. 'fragment' => 'results'
  1062. ));
  1063. $uri = $this->Socket->parseUri('http://www.cakephp.org/');
  1064. $this->assertEquals($uri, array(
  1065. 'scheme' => 'http',
  1066. 'host' => 'www.cakephp.org',
  1067. 'path' => '/'
  1068. ));
  1069. $uri = $this->Socket->parseUri('http://www.cakephp.org', true);
  1070. $this->assertEquals($uri, array(
  1071. 'scheme' => 'http',
  1072. 'host' => 'www.cakephp.org',
  1073. 'port' => 80,
  1074. 'user' => null,
  1075. 'pass' => null,
  1076. 'path' => '/',
  1077. 'query' => array(),
  1078. 'fragment' => null
  1079. ));
  1080. $uri = $this->Socket->parseUri('https://www.cakephp.org', true);
  1081. $this->assertEquals($uri, array(
  1082. 'scheme' => 'https',
  1083. 'host' => 'www.cakephp.org',
  1084. 'port' => 443,
  1085. 'user' => null,
  1086. 'pass' => null,
  1087. 'path' => '/',
  1088. 'query' => array(),
  1089. 'fragment' => null
  1090. ));
  1091. $uri = $this->Socket->parseUri('www.cakephp.org:443/query?foo', true);
  1092. $this->assertEquals($uri, array(
  1093. 'scheme' => 'https',
  1094. 'host' => 'www.cakephp.org',
  1095. 'port' => 443,
  1096. 'user' => null,
  1097. 'pass' => null,
  1098. 'path' => '/query',
  1099. 'query' => array('foo' => ""),
  1100. 'fragment' => null
  1101. ));
  1102. $uri = $this->Socket->parseUri('http://www.cakephp.org', array('host' => 'piephp.org', 'user' => 'bob', 'fragment' => 'results'));
  1103. $this->assertEquals($uri, array(
  1104. 'host' => 'www.cakephp.org',
  1105. 'user' => 'bob',
  1106. 'fragment' => 'results',
  1107. 'scheme' => 'http'
  1108. ));
  1109. $uri = $this->Socket->parseUri('https://www.cakephp.org', array('scheme' => 'http', 'port' => 23));
  1110. $this->assertEquals($uri, array(
  1111. 'scheme' => 'https',
  1112. 'port' => 23,
  1113. 'host' => 'www.cakephp.org'
  1114. ));
  1115. $uri = $this->Socket->parseUri('www.cakephp.org:59', array('scheme' => array('http', 'https'), 'port' => 80));
  1116. $this->assertEquals($uri, array(
  1117. 'scheme' => 'http',
  1118. 'port' => 59,
  1119. 'host' => 'www.cakephp.org'
  1120. ));
  1121. $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)));
  1122. $this->assertEquals($uri, array(
  1123. 'scheme' => 'http',
  1124. 'host' => 'www.google.com',
  1125. 'port' => 8080
  1126. ));
  1127. $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1&param2=value2%3Dvalue3');
  1128. $this->assertEquals($uri, array(
  1129. 'scheme' => 'http',
  1130. 'host' => 'www.cakephp.org',
  1131. 'path' => '/',
  1132. 'query' => array(
  1133. 'param1' => 'value1',
  1134. 'param2' => 'value2=value3'
  1135. )
  1136. ));
  1137. $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1&param2=value2=value3');
  1138. $this->assertEquals($uri, array(
  1139. 'scheme' => 'http',
  1140. 'host' => 'www.cakephp.org',
  1141. 'path' => '/',
  1142. 'query' => array(
  1143. 'param1' => 'value1',
  1144. 'param2' => 'value2=value3'
  1145. )
  1146. ));
  1147. }
  1148. /**
  1149. * Tests that HttpSocket::buildUri can turn all kinds of uri arrays (and strings) into fully or partially qualified URI's
  1150. *
  1151. * @return void
  1152. */
  1153. public function testBuildUri() {
  1154. $this->Socket->reset();
  1155. $r = $this->Socket->buildUri(true);
  1156. $this->assertEquals($r, false);
  1157. $r = $this->Socket->buildUri('foo.com');
  1158. $this->assertEquals($r, 'http://foo.com/');
  1159. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org'));
  1160. $this->assertEquals($r, 'http://www.cakephp.org/');
  1161. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https'));
  1162. $this->assertEquals($r, 'https://www.cakephp.org/');
  1163. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'port' => 23));
  1164. $this->assertEquals($r, 'http://www.cakephp.org:23/');
  1165. $r = $this->Socket->buildUri(array('path' => 'www.google.com/search', 'query' => 'q=cakephp'));
  1166. $this->assertEquals($r, 'http://www.google.com/search?q=cakephp');
  1167. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https', 'port' => 79));
  1168. $this->assertEquals($r, 'https://www.cakephp.org:79/');
  1169. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => 'foo'));
  1170. $this->assertEquals($r, 'http://www.cakephp.org/foo');
  1171. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/foo'));
  1172. $this->assertEquals($r, 'http://www.cakephp.org/foo');
  1173. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/search', 'query' => array('q' => 'HttpSocket')));
  1174. $this->assertEquals($r, 'http://www.cakephp.org/search?q=HttpSocket');
  1175. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar'));
  1176. $this->assertEquals($r, 'http://www.cakephp.org/#bar');
  1177. $r = $this->Socket->buildUri(array(
  1178. 'scheme' => 'https',
  1179. 'host' => 'www.cakephp.org',
  1180. 'port' => 25,
  1181. 'user' => 'bob',
  1182. 'pass' => 'secret',
  1183. 'path' => '/cool',
  1184. 'query' => array('foo' => 'bar'),
  1185. 'fragment' => 'comment'
  1186. ));
  1187. $this->assertEquals($r, 'https://bob:secret@www.cakephp.org:25/cool?foo=bar#comment');
  1188. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar'), '%fragment?%host');
  1189. $this->assertEquals($r, 'bar?www.cakephp.org');
  1190. $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org'), '%fragment???%host');
  1191. $this->assertEquals($r, '???www.cakephp.org');
  1192. $r = $this->Socket->buildUri(array('path' => '*'), '/%path?%query');
  1193. $this->assertEquals($r, '*');
  1194. $r = $this->Socket->buildUri(array('scheme' => 'foo', 'host' => 'www.cakephp.org'));
  1195. $this->assertEquals($r, 'foo://www.cakephp.org:80/');
  1196. }
  1197. /**
  1198. * Asserts that HttpSocket::parseQuery is working properly
  1199. *
  1200. * @return void
  1201. */
  1202. public function testParseQuery() {
  1203. $this->Socket->reset();
  1204. $query = $this->Socket->parseQuery(array('framework' => 'cakephp'));
  1205. $this->assertEquals($query, array('framework' => 'cakephp'));
  1206. $query = $this->Socket->parseQuery('');
  1207. $this->assertEquals($query, array());
  1208. $query = $this->Socket->parseQuery('framework=cakephp');
  1209. $this->assertEquals($query, array('framework' => 'cakephp'));
  1210. $query = $this->Socket->parseQuery('?framework=cakephp');
  1211. $this->assertEquals($query, array('framework' => 'cakephp'));
  1212. $query = $this->Socket->parseQuery('a&b&c');
  1213. $this->assertEquals($query, array('a' => '', 'b' => '', 'c' => ''));
  1214. $query = $this->Socket->parseQuery('value=12345');
  1215. $this->assertEquals($query, array('value' => '12345'));
  1216. $query = $this->Socket->parseQuery('a[0]=foo&a[1]=bar&a[2]=cake');
  1217. $this->assertEquals($query, array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')));
  1218. $query = $this->Socket->parseQuery('a[]=foo&a[]=bar&a[]=cake');
  1219. $this->assertEquals($query, array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')));
  1220. $query = $this->Socket->parseQuery('a[][]=foo&a[][]=bar&a[][]=cake');
  1221. $expectedQuery = array(
  1222. 'a' => array(
  1223. 0 => array(
  1224. 0 => 'foo'
  1225. ),
  1226. 1 => array(
  1227. 0 => 'bar'
  1228. ),
  1229. array(
  1230. 0 => 'cake'
  1231. )
  1232. )
  1233. );
  1234. $this->assertEquals($query, $expectedQuery);
  1235. $query = $this->Socket->parseQuery('a[][]=foo&a[bar]=php&a[][]=bar&a[][]=cake');
  1236. $expectedQuery = array(
  1237. 'a' => array(
  1238. array('foo'),
  1239. 'bar' => 'php',
  1240. array('bar'),
  1241. array('cake')
  1242. )
  1243. );
  1244. $this->assertEquals($query, $expectedQuery);
  1245. $query = $this->Socket->parseQuery('user[]=jim&user[3]=tom&user[]=bob');
  1246. $expectedQuery = array(
  1247. 'user' => array(
  1248. 0 => 'jim',
  1249. 3 => 'tom',
  1250. 4 => 'bob'
  1251. )
  1252. );
  1253. $this->assertEquals($query, $expectedQuery);
  1254. $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';
  1255. $query = $this->Socket->parseQuery($queryStr);
  1256. $expectedQuery = array(
  1257. 'user' => array(
  1258. 0 => array(
  1259. 'items' => array(
  1260. 'foo',
  1261. 'bar'
  1262. )
  1263. ),
  1264. 1 => array(
  1265. 'name' => 'jim',
  1266. 'items' => array(
  1267. 'personal' => array(
  1268. 'book'
  1269. , 'pen'
  1270. ),
  1271. 'ball'
  1272. )
  1273. ),
  1274. 'count' => '2'
  1275. ),
  1276. 'empty' => ''
  1277. );
  1278. $this->assertEquals($query, $expectedQuery);
  1279. }
  1280. /**
  1281. * Tests that HttpSocket::buildHeader can turn a given $header array into a proper header string according to
  1282. * HTTP 1.1 specs.
  1283. *
  1284. * @return void
  1285. */
  1286. public function testBuildHeader() {
  1287. $this->Socket->reset();
  1288. $r = $this->Socket->buildHeader(true);
  1289. $this->assertEquals($r, false);
  1290. $r = $this->Socket->buildHeader('My raw header');
  1291. $this->assertEquals($r, 'My raw header');
  1292. $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org'));
  1293. $this->assertEquals($r, "Host: www.cakephp.org\r\n");
  1294. $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org', 'Connection' => 'Close'));
  1295. $this->assertEquals($r, "Host: www.cakephp.org\r\nConnection: Close\r\n");
  1296. $r = $this->Socket->buildHeader(array('People' => array('Bob', 'Jim', 'John')));
  1297. $this->assertEquals($r, "People: Bob,Jim,John\r\n");
  1298. $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\nMulti Line field"));
  1299. $this->assertEquals($r, "Multi-Line-Field: This is my\r\n Multi Line field\r\n");
  1300. $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n Multi Line field"));
  1301. $this->assertEquals($r, "Multi-Line-Field: This is my\r\n Multi Line field\r\n");
  1302. $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n\tMulti Line field"));
  1303. $this->assertEquals($r, "Multi-Line-Field: This is my\r\n\tMulti Line field\r\n");
  1304. $r = $this->Socket->buildHeader(array('Test@Field' => "My value"));
  1305. $this->assertEquals($r, "Test\"@\"Field: My value\r\n");
  1306. }
  1307. /**
  1308. * testBuildCookies method
  1309. *
  1310. * @return void
  1311. * @todo Test more scenarios
  1312. */
  1313. public function testBuildCookies() {
  1314. $cookies = array(
  1315. 'foo' => array(
  1316. 'value' => 'bar'
  1317. ),
  1318. 'people' => array(
  1319. 'value' => 'jim,jack,johnny;',
  1320. 'path' => '/accounts'
  1321. )
  1322. );
  1323. $expect = "Cookie: foo=bar; people=jim,jack,johnny\";\"\r\n";
  1324. $result = $this->Socket->buildCookies($cookies);
  1325. $this->assertEquals($result, $expect);
  1326. }
  1327. /**
  1328. * Tests that HttpSocket::_tokenEscapeChars() returns the right characters.
  1329. *
  1330. * @return void
  1331. */
  1332. public function testTokenEscapeChars() {
  1333. $this->Socket->reset();
  1334. $expected = array(
  1335. '\x22','\x28','\x29','\x3c','\x3e','\x40','\x2c','\x3b','\x3a','\x5c','\x2f','\x5b','\x5d','\x3f','\x3d','\x7b',
  1336. '\x7d','\x20','\x00','\x01','\x02','\x03','\x04','\x05','\x06','\x07','\x08','\x09','\x0a','\x0b','\x0c','\x0d',
  1337. '\x0e','\x0f','\x10','\x11','\x12','\x13','\x14','\x15','\x16','\x17','\x18','\x19','\x1a','\x1b','\x1c','\x1d',
  1338. '\x1e','\x1f','\x7f'
  1339. );
  1340. $r = $this->Socket->tokenEscapeChars();
  1341. $this->assertEquals($r, $expected);
  1342. foreach ($expected as $key => $char) {
  1343. $expected[$key] = chr(hexdec(substr($char, 2)));
  1344. }
  1345. $r = $this->Socket->tokenEscapeChars(false);
  1346. $this->assertEquals($r, $expected);
  1347. }
  1348. /**
  1349. * Test that HttpSocket::escapeToken is escaping all characters as descriped in RFC 2616 (HTTP 1.1 specs)
  1350. *
  1351. * @return void
  1352. */
  1353. public function testEscapeToken() {
  1354. $this->Socket->reset();
  1355. $this->assertEquals($this->Socket->escapeToken('Foo'), 'Foo');
  1356. $escape = $this->Socket->tokenEscapeChars(false);
  1357. foreach ($escape as $char) {
  1358. $token = 'My-special-' . $char . '-Token';
  1359. $escapedToken = $this->Socket->escapeToken($token);
  1360. $expectedToken = 'My-special-"' . $char . '"-Token';
  1361. $this->assertEquals($escapedToken, $expectedToken, 'Test token escaping for ASCII '.ord($char));
  1362. }
  1363. $token = 'Extreme-:Token- -"@-test';
  1364. $escapedToken = $this->Socket->escapeToken($token);
  1365. $expectedToken = 'Extreme-":"Token-" "-""""@"-test';
  1366. $this->assertEquals($expectedToken, $escapedToken);
  1367. }
  1368. /**
  1369. * This tests asserts HttpSocket::reset() resets a HttpSocket instance to it's initial state (before Object::__construct
  1370. * got executed)
  1371. *
  1372. * @return void
  1373. */
  1374. public function testReset() {
  1375. $this->Socket->reset();
  1376. $initialState = get_class_vars('HttpSocket');
  1377. foreach ($initialState as $property => $value) {
  1378. $this->Socket->{$property} = 'Overwritten';
  1379. }
  1380. $return = $this->Socket->reset();
  1381. foreach ($initialState as $property => $value) {
  1382. $this->assertEquals($this->Socket->{$property}, $value);
  1383. }
  1384. $this->assertEquals($return, true);
  1385. }
  1386. /**
  1387. * This tests asserts HttpSocket::reset(false) resets certain HttpSocket properties to their initial state (before
  1388. * Object::__construct got executed).
  1389. *
  1390. * @return void
  1391. */
  1392. public function testPartialReset() {
  1393. $this->Socket->reset();
  1394. $partialResetProperties = array('request', 'response');
  1395. $initialState = get_class_vars('HttpSocket');
  1396. foreach ($initialState as $property => $value) {
  1397. $this->Socket->{$property} = 'Overwritten';
  1398. }
  1399. $return = $this->Socket->reset(false);
  1400. foreach ($initialState as $property => $originalValue) {
  1401. if (in_array($property, $partialResetProperties)) {
  1402. $this->assertEquals($this->Socket->{$property}, $originalValue);
  1403. } else {
  1404. $this->assertEquals($this->Socket->{$property}, 'Overwritten');
  1405. }
  1406. }
  1407. $this->assertEquals($return, true);
  1408. }
  1409. }