RequestTest.php 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\tests\cases\action;
  9. use lithium\action\Request;
  10. use lithium\tests\mocks\action\MockIisRequest;
  11. use lithium\tests\mocks\action\MockNginxRequest;
  12. use lithium\tests\mocks\action\MockCgiRequest;
  13. class RequestTest extends \lithium\test\Unit {
  14. public $request = null;
  15. protected $_server = array();
  16. protected $_env = array();
  17. public function setUp() {
  18. $this->_server = $_SERVER;
  19. $this->_env = $_ENV;
  20. $this->request = new Request(array('init' => false));
  21. }
  22. public function tearDown() {
  23. $_SERVER = $this->_server;
  24. $_ENV = $this->_env;
  25. unset($this->request);
  26. }
  27. public function testInitData() {
  28. $_POST['Article']['title'] = 'cool';
  29. $request = new Request();
  30. $expected = array('Article' => array('title' => 'cool'));
  31. $result = $request->data;
  32. $this->assertEqual($expected, $result);
  33. unset($_POST, $request);
  34. }
  35. public function testInitMethodOverride() {
  36. $_POST['Article']['title'] = 'cool';
  37. $request = new Request(array('env' => array('HTTP_X_HTTP_METHOD_OVERRIDE' => 'GET')));
  38. $this->assertEqual('GET', $request->env('REQUEST_METHOD'));
  39. $this->assertEqual(array('Article' => array('title' => 'cool')), $request->data);
  40. unset($_POST);
  41. }
  42. public function testInitMethodOverrideWithEmptyServer() {
  43. $_POST['Article']['title'] = 'cool';
  44. $request = new Request(array('env' => array('HTTP_X_HTTP_METHOD_OVERRIDE' => 'POST')));
  45. $this->assertEqual('POST', $request->env('REQUEST_METHOD'));
  46. $this->assertEqual(array('Article' => array('title' => 'cool')), $request->data);
  47. unset($_POST['Article']);
  48. }
  49. public function testScriptFilename() {
  50. $request = new Request(array('env' => array(
  51. 'SCRIPT_FILENAME' => '/lithium/app/webroot/index.php'
  52. )));
  53. $result = $request->env('SCRIPT_FILENAME');
  54. $this->assertEqual('/lithium/app/webroot/index.php', $result);
  55. }
  56. public function testPlatform() {
  57. $request = new MockIisRequest();
  58. $result = $request->env('PLATFORM');
  59. $this->assertEqual('IIS', $result);
  60. }
  61. public function testScriptFilenameTranslatedForIIS() {
  62. $request = new MockIisRequest();
  63. $this->assertEqual('\\lithium\\app\\webroot\\index.php', $request->env('SCRIPT_FILENAME'));
  64. $request = new Request(array('env' => array('SCRIPT_FILENAME' => null)));
  65. $path = $request->env('DOCUMENT_ROOT') . $request->env('PHP_SELF');
  66. $this->assertEqual($path, $request->env('SCRIPT_FILENAME'));
  67. }
  68. public function testDocumentRoot() {
  69. $request = new Request(array(
  70. 'env' => array('DOCUMENT_ROOT' => '/home/lithium/app/webroot')
  71. ));
  72. $this->assertEqual('/home/lithium/app/webroot', $request->env('DOCUMENT_ROOT'));
  73. }
  74. public function testDocumentRootTranslatedForIIS() {
  75. $request = new MockIisRequest();
  76. $expected = '\\lithium\\app\\webroot';
  77. $result = $request->env('DOCUMENT_ROOT');
  78. $this->assertEqual($expected, $result);
  79. }
  80. public function testScriptName() {
  81. $request = new Request(array(
  82. 'env' => array('HTTPS' => true, 'SCRIPT_NAME' => 'index.php')
  83. ));
  84. $this->assertEqual('index.php', $request->env('SCRIPT_NAME'));
  85. }
  86. public function testHttps() {
  87. $request = new Request(array('env' => array('HTTPS' => true)));
  88. $this->assertTrue($request->env('HTTPS'));
  89. }
  90. public function testHttpsFromScriptUri() {
  91. $request = new Request(array('env' => array(
  92. 'SCRIPT_URI' => 'https://lithium.com',
  93. 'HTTPS' => null
  94. )));
  95. $this->assertTrue($request->env('HTTPS'));
  96. }
  97. public function testRemoteAddr() {
  98. $request = new Request(array('env' => array('REMOTE_ADDR' => '123.456.789.000')));
  99. $this->assertEqual('123.456.789.000', $request->env('REMOTE_ADDR'));
  100. $request = new Request(array('env' => array(
  101. 'REMOTE_ADDR' => '123.456.789.000',
  102. 'HTTP_X_FORWARDED_FOR' => '111.222.333.444'
  103. )));
  104. $this->assertEqual('111.222.333.444', $request->env('REMOTE_ADDR'));
  105. $request = new Request(array('env' => array(
  106. 'REMOTE_ADDR' => '123.456.789.000',
  107. 'HTTP_PC_REMOTE_ADDR' => '222.333.444.555'
  108. )));
  109. $this->assertEqual('222.333.444.555', $request->env('REMOTE_ADDR'));
  110. $request = new Request(array('env' => array(
  111. 'REMOTE_ADDR' => '123.456.789.000',
  112. 'HTTP_X_REAL_IP' => '111.222.333.444'
  113. )));
  114. $this->assertEqual('111.222.333.444', $request->env('REMOTE_ADDR'));
  115. $request = new Request(array('env' => array(
  116. 'REMOTE_ADDR' => '123.456.789.000',
  117. 'HTTP_X_FORWARDED_FOR' => '111.222.333.444',
  118. 'HTTP_PC_REMOTE_ADDR' => '222.333.444.555'
  119. )));
  120. $this->assertEqual('111.222.333.444', $request->env('REMOTE_ADDR'));
  121. }
  122. public function testRemoteAddrFromHttpPcRemoteAddr() {
  123. $request = new MockIisRequest();
  124. $this->assertEqual('123.456.789.000', $request->env('REMOTE_ADDR'));
  125. }
  126. public function testBase() {
  127. $request = new Request(array('env' => array('PHP_SELF' => '/index.php')));
  128. $this->assertFalse($request->env('base'));
  129. }
  130. public function testBaseWithDirectory() {
  131. $request = new Request(array('env' => array(
  132. 'PHP_SELF' => '/lithium.com/app/webroot/index.php'
  133. )));
  134. $this->assertEqual('/lithium.com', $request->env('base'));
  135. }
  136. public function testRequestWithoutUrlQueryParam() {
  137. unset($_GET['url']);
  138. $request = new Request(array('env' => array(
  139. 'PHP_SELF' => '/test_app/app/webroot/index.php',
  140. 'REQUEST_URI' => '/test_app/'
  141. )));
  142. $this->assertEqual('/test_app', $request->env('base'));
  143. $this->assertEqual('/', $request->url);
  144. $request = new Request(array('env' => array(
  145. 'PHP_SELF' => '/test_app/app/webroot/index.php',
  146. 'REQUEST_URI' => '/test_app/pages/test_app'
  147. )));
  148. $this->assertEqual('/test_app', $request->env('base'));
  149. $this->assertEqual('pages/test_app', $request->url);
  150. }
  151. public function testRequestWithColon() {
  152. unset($_GET['url']);
  153. $request = new Request(array('env' => array(
  154. 'PHP_SELF' => '/test_app/app/webroot/index.php',
  155. 'REQUEST_URI' => '/test_app/pages/test_app/test:a'
  156. )));
  157. $this->assertEqual('/test_app', $request->env('base'));
  158. $this->assertEqual('pages/test_app/test:a', $request->url);
  159. $request = new Request(array('env' => array(
  160. 'PHP_SELF' => '/test_app/app/webroot/index.php',
  161. 'REQUEST_URI' => '/test_app/pages/test_app/test:1'
  162. )));
  163. $this->assertEqual('/test_app', $request->env('base'));
  164. $this->assertEqual('pages/test_app/test:1', $request->url);
  165. }
  166. public function testRequestWithoutUrlQueryParamAndNoApp() {
  167. unset($_GET['url']);
  168. $request = new Request(array('env' => array(
  169. 'PHP_SELF' => '/test_app/webroot/index.php',
  170. 'REQUEST_URI' => '/test_app/'
  171. )));
  172. $this->assertEqual('/test_app', $request->env('base'));
  173. $this->assertEqual('/', $request->url);
  174. }
  175. public function testRequestWithoutUrlQueryParamAndNoAppOrWebroot() {
  176. unset($_GET['url']);
  177. $request = new Request(array('env' => array(
  178. 'PHP_SELF' => '/test_app/index.php',
  179. 'REQUEST_URI' => '/test_app/'
  180. )));
  181. $this->assertEqual('/test_app', $request->env('base'));
  182. $this->assertEqual('/', $request->url);
  183. }
  184. public function testBaseWithAppAndOtherDirectory() {
  185. $request = new Request(array('env' => array(
  186. 'PHP_SELF' => '/lithium.com/app/other/webroot/index.php'
  187. )));
  188. $this->assertEqual('/lithium.com/app/other', $request->env('base'));
  189. }
  190. public function testPhpSelfTranslatedForIIS() {
  191. $request = new MockIisRequest();
  192. $this->assertEqual('/index.php', $request->env('PHP_SELF'));
  193. }
  194. public function testServerHttpBase() {
  195. $_SERVER['HTTP_HOST'] = 'sub.lithium.local';
  196. $request = new Request();
  197. $expected = '.lithium.local';
  198. $result = $request->env('HTTP_BASE');
  199. $this->assertEqual($expected, $result);
  200. }
  201. public function testCgiPlatform() {
  202. $request = new MockCgiRequest();
  203. $result = $request->env('CGI_MODE');
  204. $this->assertTrue($result);
  205. }
  206. public function testCgiScriptUrl() {
  207. $request = new MockCgiRequest();
  208. $expected = '/lithium/app/webroot/index.php';
  209. $result = $request->env('SCRIPT_NAME');
  210. $this->assertEqual($expected, $result);
  211. }
  212. public function testGetMethod() {
  213. $request = new Request(array('env' => array(
  214. 'PHP_SELF' => '/lithium.com/app/webroot/index.php',
  215. 'HTTP_ACCEPT' => 'text/html,application/xml,image/png,*/*',
  216. 'HTTP_ACCEPT_LANGUAGE' => 'da, en-gb;q=0.8, en;q=0.7'
  217. )));
  218. $request->data = array('Article' => array('title' => 'cool'));
  219. $expected = array('title' => 'cool');
  220. $result = $request->get('data:Article');
  221. $this->assertEqual($expected, $result);
  222. $result = $request->get('not:Post');
  223. $this->assertNull($result);
  224. $expected = '/lithium.com';
  225. $result = $request->get('env:base');
  226. $this->assertEqual($expected, $result);
  227. $accept = $request->get('http:accept');
  228. $this->assertEqual('text/html,application/xml,image/png,*/*', $accept);
  229. $this->assertEqual($request->get('http:method'), $request->env('REQUEST_METHOD'));
  230. }
  231. public function testDetect() {
  232. $request = new Request(array('env' => array('SOME_COOL_DETECTION' => true)));
  233. $request->detect('cool', 'SOME_COOL_DETECTION');
  234. $this->assertTrue($request->is('cool'));
  235. $this->assertFalse($request->is('foo'));
  236. $request = new Request(array('env' => array(
  237. 'HTTP_USER_AGENT' => 'Mozilla/5.0 (iPhone; U; XXXXX like Mac OS X; en) AppleWebKit/420+'
  238. )));
  239. $request->detect('iPhone', array('HTTP_USER_AGENT', '/iPhone/'));
  240. $isiPhone = $request->is('iPhone'); // returns true if 'iPhone' appears anywhere in the UA
  241. $this->assertTrue($isiPhone);
  242. }
  243. public function testDetectWithClosure() {
  244. $request = new Request();
  245. $request->detect('cool', function ($self) { return true; });
  246. $request->detect('notCool', function ($self) { return false; });
  247. $this->assertTrue($request->is('cool'));
  248. $this->assertFalse($request->is('notCool'));
  249. }
  250. public function testDetectWithArray() {
  251. $request = new Request();
  252. $request->detect(array('cool' => function ($self) {
  253. return true;
  254. }));
  255. $result = $request->is('cool');
  256. $this->assertTrue($result);
  257. }
  258. public function testDetectWithArrayRegex() {
  259. $request = new Request(array('env' => array('SOME_COOL_DETECTION' => 'this is cool')));
  260. $request->detect('cool', array('SOME_COOL_DETECTION', '/cool/'));
  261. $result = $request->is('cool');
  262. $this->assertTrue($result);
  263. }
  264. public function testDetectSsl() {
  265. $request = new Request(array('env' => array('SCRIPT_URI' => null, 'HTTPS' => 'off')));
  266. $this->assertFalse($request->env('HTTPS'));
  267. $request = new Request(array('env' => array('SCRIPT_URI' => null, 'HTTPS' => 'on')));
  268. $this->assertTrue($request->env('HTTPS'));
  269. $request = new Request(array('env' => array('SCRIPT_URI' => null, 'HTTPS' => null)));
  270. $this->assertFalse($request->env('HTTPS'));
  271. }
  272. public function testContentTypeDetection() {
  273. $request = new Request(array('env' => array(
  274. 'CONTENT_TYPE' => 'application/json; charset=UTF-8',
  275. 'REQUEST_METHOD' => 'POST'
  276. )));
  277. $this->assertTrue($request->is('json'));
  278. $this->assertFalse($request->is('html'));
  279. $this->assertFalse($request->is('foo'));
  280. }
  281. public function testIsMobile() {
  282. $iPhone = 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like ';
  283. $iPhone .= 'Gecko) Version/3.0 Mobile/1A535b Safari/419.3';
  284. $request = new Request(array('env' => array('HTTP_USER_AGENT' => $iPhone)));
  285. $this->assertTrue($request->is('mobile'));
  286. $android = 'Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+ (KHTML, like ';
  287. $android .= 'Gecko) Safari/419.3';
  288. $request = new Request(array('env' => array('HTTP_USER_AGENT' => $android)));
  289. $this->assertTrue($request->is('mobile'));
  290. }
  291. public function testType() {
  292. $request = new Request();
  293. $this->assertEqual('html', $request->type());
  294. $request = new Request(array('env' => array(
  295. 'CONTENT_TYPE' => 'application/json; charset=UTF-8',
  296. 'REQUEST_METHOD' => 'POST'
  297. )));
  298. $this->assertEqual('application/json; charset=UTF-8', $request->env('CONTENT_TYPE'));
  299. $this->assertEqual('json', $request->type());
  300. }
  301. public function testTypeforNginx() {
  302. $request = new MockNginxRequest();
  303. $this->assertEqual('html', $request->type());
  304. }
  305. public function testRefererDefault() {
  306. $_SERVER['HTTP_REFERER'] = null;
  307. $request = new Request();
  308. $expected = '/';
  309. $result = $request->referer('/');
  310. $this->assertEqual($expected, $result);
  311. }
  312. public function testRefererNotLocal() {
  313. $_SERVER['HTTP_REFERER'] = 'http://lithium.com/posts/index';
  314. $request = new Request();
  315. $expected = 'http://lithium.com/posts/index';
  316. $result = $request->referer('/');
  317. $this->assertEqual($expected, $result);
  318. }
  319. public function testRefererLocal() {
  320. $_SERVER['HTTP_REFERER'] = '/posts/index';
  321. $request = new Request();
  322. $expected = '/posts/index';
  323. $result = $request->referer('/', true);
  324. $this->assertEqual($expected, $result);
  325. }
  326. public function testRefererLocalFromNotLocal() {
  327. $_SERVER['HTTP_REFERER'] = 'http://lithium.com/posts/index';
  328. $request = new Request();
  329. $expected = '/';
  330. $result = $request->referer('/', true);
  331. $this->assertEqual($expected, $result);
  332. }
  333. public function testMagicParamsAccess() {
  334. $this->assertNull($this->request->action);
  335. $this->assertFalse(isset($this->request->params['action']));
  336. $this->assertFalse(isset($this->request->action));
  337. $expected = $this->request->params['action'] = 'index';
  338. $this->assertEqual($expected, $this->request->action);
  339. $this->assertTrue(isset($this->request->action));
  340. }
  341. public function testSingleFileNormalization() {
  342. $_FILES = array(
  343. 'file' => array(
  344. 'name' => 'file.jpg',
  345. 'type' => 'image/jpeg',
  346. 'tmp_name' => '/private/var/tmp/phpows38J',
  347. 'error' => 0,
  348. 'size' => 418
  349. )
  350. );
  351. $request = new Request();
  352. $expected = array('file' => array(
  353. 'name' => 'file.jpg',
  354. 'type' => 'image/jpeg',
  355. 'tmp_name' => '/private/var/tmp/phpows38J',
  356. 'error' => 0,
  357. 'size' => 418
  358. ));
  359. $result = $request->data;
  360. $this->assertEqual($expected, $result);
  361. unset($_FILES, $request);
  362. }
  363. public function testDeepFileNormalization() {
  364. $_FILES = array(
  365. 'files' => array(
  366. 'name' => array(
  367. 0 => 'file 2.jpg',
  368. 1 => 'file 3.jpg',
  369. 2 => 'file 4.jpg'
  370. ),
  371. 'type' => array(
  372. 0 => 'image/jpeg',
  373. 1 => 'image/jpeg',
  374. 2 => 'image/jpeg'
  375. ),
  376. 'tmp_name' => array(
  377. 0 => '/private/var/tmp/phpF5vsky',
  378. 1 => '/private/var/tmp/phphRJ2zW',
  379. 2 => '/private/var/tmp/phprI92L1'
  380. ),
  381. 'error' => array(
  382. 0 => 0,
  383. 1 => 0,
  384. 2 => 0
  385. ),
  386. 'size' => array(
  387. 0 => 418,
  388. 1 => 418,
  389. 2 => 418
  390. )
  391. )
  392. );
  393. $request = new Request();
  394. $expected = array('files' => array(
  395. 0 => array(
  396. 'name' => 'file 2.jpg',
  397. 'type' => 'image/jpeg',
  398. 'tmp_name' => '/private/var/tmp/phpF5vsky',
  399. 'error' => 0,
  400. 'size' => 418
  401. ),
  402. 1 => array(
  403. 'name' => 'file 3.jpg',
  404. 'type' => 'image/jpeg',
  405. 'tmp_name' => '/private/var/tmp/phphRJ2zW',
  406. 'error' => 0,
  407. 'size' => 418
  408. ),
  409. 2 => array(
  410. 'name' => 'file 4.jpg',
  411. 'type' => 'image/jpeg',
  412. 'tmp_name' => '/private/var/tmp/phprI92L1',
  413. 'error' => 0,
  414. 'size' => 418
  415. )
  416. ));
  417. $result = $request->data;
  418. $this->assertEqual($expected, $result);
  419. unset($_FILES, $request);
  420. }
  421. public function testNestedFilesNormalization() {
  422. $_FILES = array('Image' => array(
  423. 'name' => array(
  424. 'file' => 'file 5.jpg'
  425. ),
  426. 'type' => array(
  427. 'file' => 'image/jpeg'
  428. ),
  429. 'tmp_name' => array(
  430. 'file' => '/private/var/tmp/phpAmSDL4'
  431. ),
  432. 'error' => array(
  433. 'file' => 0
  434. ),
  435. 'size' => array(
  436. 'file' => 418
  437. )
  438. ));
  439. $request = new Request();
  440. $expected = array('Image' => array(
  441. 'file' => array(
  442. 'name' => 'file 5.jpg',
  443. 'type' => 'image/jpeg',
  444. 'tmp_name' => '/private/var/tmp/phpAmSDL4',
  445. 'error' => 0,
  446. 'size' => 418
  447. )
  448. ));
  449. $result = $request->data;
  450. $this->assertEqual($expected, $result);
  451. unset($_FILES, $request);
  452. }
  453. public function testNestedDeepFilesNormalization() {
  454. $_FILES = array('Photo' => array(
  455. 'name' => array(
  456. 'files' => array(
  457. 0 => 'file 6.jpg',
  458. 1 => 'file 7.jpg',
  459. 2 => 'file 8.jpg'
  460. )
  461. ),
  462. 'type' => array(
  463. 'files' => array(
  464. 0 => 'image/jpeg',
  465. 1 => 'image/jpeg',
  466. 2 => 'image/jpeg'
  467. )
  468. ),
  469. 'tmp_name' => array(
  470. 'files' => array(
  471. 0 => '/private/var/tmp/php2eViak',
  472. 1 => '/private/var/tmp/phpMsC5Pp',
  473. 2 => '/private/var/tmp/phpm2nm98'
  474. )
  475. ),
  476. 'error' => array(
  477. 'files' => array(
  478. 0 => 0,
  479. 1 => 0,
  480. 2 => 0
  481. )
  482. ),
  483. 'size' => array(
  484. 'files' => array(
  485. 0 => 418,
  486. 1 => 418,
  487. 2 => 418
  488. )
  489. )
  490. ));
  491. $request = new Request();
  492. $expected = array('Photo' => array(
  493. 'files' => array(
  494. 0 => array(
  495. 'name' => 'file 6.jpg',
  496. 'type' => 'image/jpeg',
  497. 'tmp_name' => '/private/var/tmp/php2eViak',
  498. 'error' => 0,
  499. 'size' => 418
  500. ),
  501. 1 => array(
  502. 'name' => 'file 7.jpg',
  503. 'type' => 'image/jpeg',
  504. 'tmp_name' => '/private/var/tmp/phpMsC5Pp',
  505. 'error' => 0,
  506. 'size' => 418
  507. ),
  508. 2 => array(
  509. 'name' => 'file 8.jpg',
  510. 'type' => 'image/jpeg',
  511. 'tmp_name' => '/private/var/tmp/phpm2nm98',
  512. 'error' => 0,
  513. 'size' => 418
  514. )
  515. )
  516. ));
  517. $result = $request->data;
  518. $this->assertEqual($expected, $result);
  519. unset($_FILES, $request);
  520. }
  521. public function testMixedFilesNormalization() {
  522. $_FILES = array(
  523. 'file' => array(
  524. 'name' => 'file.jpg',
  525. 'type' => 'image/jpeg',
  526. 'tmp_name' => '/private/var/tmp/phpows38J',
  527. 'error' => 0,
  528. 'size' => 418
  529. ),
  530. 'files' => array(
  531. 'name' => array(
  532. 0 => 'file 2.jpg',
  533. 1 => 'file 3.jpg',
  534. 2 => 'file 4.jpg'
  535. ),
  536. 'type' => array(
  537. 0 => 'image/jpeg',
  538. 1 => 'image/jpeg',
  539. 2 => 'image/jpeg'
  540. ),
  541. 'tmp_name' => array(
  542. 0 => '/private/var/tmp/phpF5vsky',
  543. 1 => '/private/var/tmp/phphRJ2zW',
  544. 2 => '/private/var/tmp/phprI92L1'
  545. ),
  546. 'error' => array(
  547. 0 => 0,
  548. 1 => 0,
  549. 2 => 0
  550. ),
  551. 'size' => array(
  552. 0 => 418,
  553. 1 => 418,
  554. 2 => 418
  555. )
  556. ),
  557. 'Image' => array(
  558. 'name' => array(
  559. 'file' => 'file 5.jpg'
  560. ),
  561. 'type' => array(
  562. 'file' => 'image/jpeg'
  563. ),
  564. 'tmp_name' => array(
  565. 'file' => '/private/var/tmp/phpAmSDL4'
  566. ),
  567. 'error' => array(
  568. 'file' => 0
  569. ),
  570. 'size' => array(
  571. 'file' => 418
  572. )
  573. ),
  574. 'Photo' => array(
  575. 'name' => array(
  576. 'files' => array(
  577. 0 => 'file 6.jpg',
  578. 1 => 'file 7.jpg',
  579. 2 => 'file 8.jpg'
  580. )
  581. ),
  582. 'type' => array(
  583. 'files' => array(
  584. 0 => 'image/jpeg',
  585. 1 => 'image/jpeg',
  586. 2 => 'image/jpeg'
  587. )
  588. ),
  589. 'tmp_name' => array(
  590. 'files' => array(
  591. 0 => '/private/var/tmp/php2eViak',
  592. 1 => '/private/var/tmp/phpMsC5Pp',
  593. 2 => '/private/var/tmp/phpm2nm98'
  594. )
  595. ),
  596. 'error' => array(
  597. 'files' => array(
  598. 0 => 0,
  599. 1 => 0,
  600. 2 => 0
  601. )
  602. ),
  603. 'size' => array(
  604. 'files' => array(
  605. 0 => 418,
  606. 1 => 418,
  607. 2 => 418
  608. )
  609. )
  610. )
  611. );
  612. $expected = array(
  613. 'file' => array(
  614. 'name' => 'file.jpg',
  615. 'type' => 'image/jpeg',
  616. 'tmp_name' => '/private/var/tmp/phpows38J',
  617. 'error' => 0,
  618. 'size' => 418
  619. ),
  620. 'files' => array(
  621. 0 => array(
  622. 'name' => 'file 2.jpg',
  623. 'type' => 'image/jpeg',
  624. 'tmp_name' => '/private/var/tmp/phpF5vsky',
  625. 'error' => 0,
  626. 'size' => 418
  627. ),
  628. 1 => array(
  629. 'name' => 'file 3.jpg',
  630. 'type' => 'image/jpeg',
  631. 'tmp_name' => '/private/var/tmp/phphRJ2zW',
  632. 'error' => 0,
  633. 'size' => 418
  634. ),
  635. 2 => array(
  636. 'name' => 'file 4.jpg',
  637. 'type' => 'image/jpeg',
  638. 'tmp_name' => '/private/var/tmp/phprI92L1',
  639. 'error' => 0,
  640. 'size' => 418
  641. )
  642. ),
  643. 'Image' => array(
  644. 'file' => array(
  645. 'name' => 'file 5.jpg',
  646. 'type' => 'image/jpeg',
  647. 'tmp_name' => '/private/var/tmp/phpAmSDL4',
  648. 'error' => 0,
  649. 'size' => 418
  650. )
  651. ),
  652. 'Photo' => array(
  653. 'files' => array(
  654. 0 => array(
  655. 'name' => 'file 6.jpg',
  656. 'type' => 'image/jpeg',
  657. 'tmp_name' => '/private/var/tmp/php2eViak',
  658. 'error' => 0,
  659. 'size' => 418
  660. ),
  661. 1 => array(
  662. 'name' => 'file 7.jpg',
  663. 'type' => 'image/jpeg',
  664. 'tmp_name' => '/private/var/tmp/phpMsC5Pp',
  665. 'error' => 0,
  666. 'size' => 418
  667. ),
  668. 2 => array(
  669. 'name' => 'file 8.jpg',
  670. 'type' => 'image/jpeg',
  671. 'tmp_name' => '/private/var/tmp/phpm2nm98',
  672. 'error' => 0,
  673. 'size' => 418
  674. )
  675. )
  676. )
  677. );
  678. $request = new Request();
  679. $result = $request->data;
  680. $this->assertEqual($expected, $result);
  681. unset($_FILES, $request);
  682. }
  683. public function testRequestTypeAccessors() {
  684. $request = new Request(array('env' => array('REQUEST_METHOD' => 'GET')));
  685. $this->assertTrue($request->is('get'));
  686. $this->assertFalse($request->is('post'));
  687. $request = new Request(array('env' => array('REQUEST_METHOD' => 'POST')));
  688. $this->assertTrue($request->is('post'));
  689. $this->assertFalse($request->is('get'));
  690. $this->assertFalse($request->is('put'));
  691. $request = new Request(array('env' => array('REQUEST_METHOD' => 'PUT')));
  692. $this->assertTrue($request->is('put'));
  693. $this->assertFalse($request->is('get'));
  694. $this->assertFalse($request->is('post'));
  695. }
  696. public function testRequestTypeIsMobile() {
  697. $request = new Request(array('env' => array(
  698. 'HTTP_USER_AGENT' => 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en)'
  699. )));
  700. $this->assertTrue($request->is('mobile'));
  701. }
  702. public function testUrlFromGet() {
  703. $_GET['url'] = 'posts/1';
  704. $request = new Request();
  705. $expected = 'posts/1';
  706. $result = $request->url;
  707. $this->assertEqual($expected, $result);
  708. unset($_GET);
  709. }
  710. public function testUrlFromConstructor() {
  711. $request = new Request(array('url' => 'posts/1'));
  712. $expected = 'posts/1';
  713. $result = $request->url;
  714. $this->assertEqual($expected, $result);
  715. }
  716. public function testDataFromConstructor() {
  717. $request = new Request(array('data' => array('name' => 'bob')));
  718. $expected = array('name' => 'bob');
  719. $result = $request->data;
  720. $this->assertEqual($expected, $result);
  721. }
  722. public function testQueryFromConstructor() {
  723. $request = new Request(array('query' => array('page' => 1)));
  724. $expected = array('page' => 1);
  725. $result = $request->query;
  726. $this->assertEqual($expected, $result);
  727. }
  728. public function testMethodOverrideFromData() {
  729. $_POST['_method'] = 'put';
  730. $request = new Request();
  731. $result = $request->is('put');
  732. $this->assertTrue($result);
  733. unset($_POST);
  734. $request = new Request(array('data' => array('_method' => 'put')));
  735. $result = $request->is('put');
  736. $this->assertTrue($result);
  737. }
  738. public function testMergeMobileDetectors() {
  739. $request = new Request(array(
  740. 'env' => array('HTTP_USER_AGENT' => 'testMobile'),
  741. 'detectors' => array('mobile' => array('HTTP_USER_AGENT', array('testMobile')))
  742. ));
  743. $result = $request->is('mobile');
  744. $this->assertTrue($result);
  745. $request = new Request(array(
  746. 'env' => array('HTTP_USER_AGENT' => 'iPhone'),
  747. 'detectors' => array('mobile' => array('HTTP_USER_AGENT', array('testMobile')))
  748. ));
  749. $result = $request->is('mobile');
  750. $this->assertTrue($result);
  751. }
  752. public function testRequestTypeFromConstruct() {
  753. $request = new Request(array('type' => 'json'));
  754. $expected = 'json';
  755. $result = $request->type();
  756. $this->assertEqual($expected, $result);
  757. }
  758. public function testRequestTypeFromParams() {
  759. $request = new Request();
  760. $request->params['type'] = 'json';
  761. $expected = 'json';
  762. $result = $request->type();
  763. $this->assertEqual($expected, $result);
  764. }
  765. public function testAutomaticContentDecoding() {
  766. foreach (array('POST', 'PUT', 'PATCH') as $method) {
  767. $stream = fopen('php://temp', 'r+');
  768. fwrite($stream, '{ "foo": "bar" }');
  769. rewind($stream);
  770. $request = new Request(compact('stream') + array('env' => array(
  771. 'CONTENT_TYPE' => 'application/json; charset=UTF-8',
  772. 'REQUEST_METHOD' => $method
  773. )));
  774. $this->assertEqual(array('foo' => 'bar'), $request->data);
  775. }
  776. foreach (array('GET', 'HEAD', 'OPTIONS', 'DELETE') as $method) {
  777. $stream = fopen('php://temp', 'r+');
  778. fwrite($stream, '{ "foo": "bar" }');
  779. rewind($stream);
  780. $request = new Request(compact('stream') + array('env' => array(
  781. 'CONTENT_TYPE' => 'application/json; charset=UTF-8',
  782. 'REQUEST_METHOD' => $method
  783. )));
  784. $this->assertFalse($request->data);
  785. }
  786. }
  787. public function testRequestTypeFromHeader() {
  788. $request = new Request(array('env' => array('CONTENT_TYPE' => 'json')));
  789. $this->assertEqual('json', $request->type());
  790. }
  791. public function testResponseTypeDetection() {
  792. $request = new Request(array('env' => array('HTTP_ACCEPT' => 'text/xml,*/*')));
  793. $this->assertEqual('xml', $request->accepts());
  794. $request->params['type'] = 'json';
  795. $this->assertEqual('json', $request->accepts());
  796. $request = new Request(array('env' => array(
  797. 'HTTP_ACCEPT' => 'application/xml,image/png,*/*'
  798. )));
  799. $this->assertEqual('xml', $request->accepts());
  800. $request = new Request(array('env' => array(
  801. 'HTTP_ACCEPT' => 'application/xml,application/xhtml+xml'
  802. )));
  803. $this->assertEqual('html', $request->accepts());
  804. $request = new Request(array('env' => array('HTTP_ACCEPT' => null)));
  805. $this->assertEqual('html', $request->accepts());
  806. }
  807. /**
  808. * Tests that accepted content-types without a `q` value are sorted in the order they appear in
  809. * the `HTTP_ACCEPT` header.
  810. */
  811. public function testAcceptTypeOrder() {
  812. $request = new Request(array('env' => array(
  813. 'HTTP_ACCEPT' => 'application/xhtml+xml,text/html'
  814. )));
  815. $expected = array('application/xhtml+xml', 'text/html');
  816. $this->assertEqual($expected, $request->accepts(true));
  817. $request = new Request(array('env' => array(
  818. 'HTTP_USER_AGENT' => 'Safari',
  819. 'HTTP_ACCEPT' => 'application/xhtml+xml,text/html,text/plain;q=0.9'
  820. )));
  821. $expected = array('application/xhtml+xml', 'text/html', 'text/plain');
  822. $this->assertEqual($expected, $request->accepts(true));
  823. }
  824. public function testParsingAcceptHeader() {
  825. $chrome = array(
  826. 'application/xml',
  827. 'application/xhtml+xml',
  828. 'text/html;q=0.9',
  829. 'text/plain;q=0.8',
  830. 'image/png',
  831. '*/*;q=0.5'
  832. );
  833. $firefox = array(
  834. 'text/html',
  835. 'application/xhtml+xml',
  836. 'application/xml;q=0.9',
  837. '*/*;q=0.8'
  838. );
  839. $safari = array(
  840. 'application/xml',
  841. 'application/xhtml+xml',
  842. 'text/html;q=0.9',
  843. 'text/plain;q=0.8',
  844. 'image/png',
  845. '*/*;q=0.5'
  846. );
  847. $opera = array(
  848. 'text/html',
  849. 'application/xml;q=0.9',
  850. 'application/xhtml+xml',
  851. 'image/png',
  852. 'image/jpeg',
  853. 'image/gif',
  854. 'image/x-xbitmap',
  855. '*/*;q=0.1'
  856. );
  857. $android = array(
  858. 'application/xml',
  859. 'application/xhtml+xml',
  860. 'text/html;q=0.9',
  861. 'text/plain;q=0.8',
  862. 'image/png',
  863. '*/*;q=0.5',
  864. 'application/youtube-client'
  865. );
  866. $request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $chrome))));
  867. $this->assertEqual('html', $request->accepts());
  868. $this->assertTrue(array_search('text/plain', $request->accepts(true)), 4);
  869. $request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $safari))));
  870. $this->assertEqual('html', $request->accepts());
  871. $request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $firefox))));
  872. $this->assertEqual('html', $request->accepts());
  873. $request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $opera))));
  874. $this->assertEqual('html', $request->accepts());
  875. $request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $chrome))));
  876. $request->params['type'] = 'txt';
  877. $result = $request->accepts(true);
  878. $this->assertEqual('text/plain', $result[0]);
  879. $request = new Request(array('env' => array('HTTP_ACCEPT' => join(',', $android))));
  880. $this->assertEqual('html', $request->accepts());
  881. }
  882. /**
  883. * Tests that `Accept` headers with only one listed content type are parsed property, and tests
  884. * that `'* /*'` is still parsed as `'text/html'`.
  885. */
  886. public function testAcceptSingleContentType() {
  887. $request = new Request(array('env' => array('HTTP_ACCEPT' => 'application/json,text/xml')));
  888. $this->assertEqual(array('application/json', 'text/xml'), $request->accepts(true));
  889. $this->assertEqual('json', $request->accepts());
  890. $request = new Request(array('env' => array('HTTP_ACCEPT' => 'application/json')));
  891. $this->assertEqual(array('application/json'), $request->accepts(true));
  892. $this->assertEqual('json', $request->accepts());
  893. $request = new Request(array('env' => array('HTTP_ACCEPT' => '*/*')));
  894. $this->assertEqual(array('text/html'), $request->accepts(true));
  895. $this->assertEqual('html', $request->accepts());
  896. }
  897. public function testLocaleDetection() {
  898. $request = new Request();
  899. $this->assertNull($request->locale());
  900. $request->params['locale'] = 'fr';
  901. $this->assertEqual('fr', $request->locale());
  902. $request->locale('de');
  903. $this->assertEqual('de', $request->locale());
  904. }
  905. /**
  906. * Tests that `action\Request` correctly inherits the functionality of the `to()` method
  907. * inherited from `lithium\net\http\Request`.
  908. */
  909. public function testConvertToUrl() {
  910. $request = new Request(array(
  911. 'env' => array('HTTP_HOST' => 'foo.com', 'HTTPS' => 'on'),
  912. 'base' => '/the/base/path',
  913. 'url' => '/the/url',
  914. 'query' => array('some' => 'query', 'parameter' => 'values')
  915. ));
  916. $expected = 'https://foo.com/the/base/path/the/url?some=query&parameter=values';
  917. $this->assertEqual($expected, $request->to('url'));
  918. $request = new Request(array(
  919. 'env' => array('HTTP_HOST' => 'foo.com'),
  920. 'base' => '/',
  921. 'url' => '/',
  922. 'query' => array()
  923. ));
  924. $expected = 'http://foo.com/';
  925. $this->assertEqual($expected, $request->to('url'));
  926. $request = new Request(array(
  927. 'url' => 'foo/bar',
  928. 'base' => null,
  929. 'env' => array('HTTP_HOST' => 'example.com', 'PHP_SELF' => '/index.php')
  930. ));
  931. $expected = 'http://example.com/foo/bar';
  932. $this->assertEqual($expected, $request->to('url'));
  933. }
  934. public function testConvertToUrl2() {
  935. $request = new Request(array(
  936. 'env' => array('HTTP_HOST' => 'foo.com', 'HTTPS' => 'on'),
  937. 'base' => '/the/base/path',
  938. 'url' => '/posts',
  939. 'params' => array('controller' => 'posts', 'action' => 'index'),
  940. 'query' => array('some' => 'query', 'parameter' => 'values')
  941. ));
  942. $expected = 'https://foo.com/the/base/path/posts?some=query&parameter=values';
  943. $this->assertEqual($expected, $request->to('url'));
  944. }
  945. /**
  946. * Tests that the HTTP request method set by `Request` from the server information is not
  947. * overwritten in a parent class.
  948. */
  949. public function testRequesMethodConfiguration() {
  950. $request = new Request(array('env' => array('REQUEST_METHOD' => 'POST')));
  951. $this->assertEqual('POST', $request->method);
  952. $request = new Request(array('env' => array('REQUEST_METHOD' => 'PATCH')));
  953. $this->assertEqual('PATCH', $request->method);
  954. }
  955. }
  956. ?>