RequestTest.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Tests\Component\HttpFoundation;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\File\UploadedFile;
  13. class RequestTest extends \PHPUnit_Framework_TestCase
  14. {
  15. /**
  16. * @covers Symfony\Component\HttpFoundation\Request::__construct
  17. */
  18. public function testConstructor()
  19. {
  20. $this->testInitialize();
  21. }
  22. /**
  23. * @covers Symfony\Component\HttpFoundation\Request::initialize
  24. */
  25. public function testInitialize()
  26. {
  27. $request = new Request();
  28. $request->initialize(array('foo' => 'bar'));
  29. $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument');
  30. $request->initialize(null, array('foo' => 'bar'));
  31. $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument');
  32. $request->initialize(null, null, array('foo' => 'bar'));
  33. $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its thrid argument');
  34. $request->initialize(null, null, null, null, null, array('HTTP_FOO' => 'bar'));
  35. $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its fourth argument');
  36. }
  37. /**
  38. * @covers Symfony\Component\HttpFoundation\Request::create
  39. */
  40. public function testCreate()
  41. {
  42. $request = Request::create('http://test.com/foo?bar=baz');
  43. $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
  44. $this->assertEquals('/foo', $request->getPathInfo());
  45. $this->assertEquals('bar=baz', $request->getQueryString());
  46. $request = Request::create('https://test.com/foo?bar=baz');
  47. $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri());
  48. $this->assertEquals('/foo', $request->getPathInfo());
  49. $this->assertEquals('bar=baz', $request->getQueryString());
  50. $this->assertEquals(443, $request->getPort());
  51. $request = Request::create('test.com:90/foo');
  52. $this->assertEquals('http://test.com:90/foo', $request->getUri());
  53. $this->assertEquals('/foo', $request->getPathInfo());
  54. $this->assertEquals('test.com', $request->getHost());
  55. $this->assertEquals(90, $request->getPort());
  56. $request = Request::create('https://test.com:90/foo');
  57. $this->assertEquals('https://test.com:90/foo', $request->getUri());
  58. $this->assertEquals('/foo', $request->getPathInfo());
  59. $this->assertEquals('test.com', $request->getHost());
  60. $this->assertEquals(90, $request->getPort());
  61. }
  62. /**
  63. * @covers Symfony\Component\HttpFoundation\Request::duplicate
  64. */
  65. public function testDuplicate()
  66. {
  67. $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar'));
  68. $dup = $request->duplicate();
  69. $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters');
  70. $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters');
  71. $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes');
  72. $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers');
  73. $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar'));
  74. $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided');
  75. $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided');
  76. $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided');
  77. $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided');
  78. }
  79. /**
  80. * @covers Symfony\Component\HttpFoundation\Request::getFormat
  81. */
  82. public function testGetFormat()
  83. {
  84. $request = new Request();
  85. $this->assertNull($request->getFormat(null), '->getFormat() returns null when mime-type is null');
  86. $this->assertNull($request->getFormat('unexistant-mime-type'), '->getFormat() returns null when mime-type is unknown');
  87. $this->assertEquals('txt', $request->getFormat('text/plain'), '->getFormat() returns correct format when mime-type have one format only');
  88. $this->assertEquals('js', $request->getFormat('application/javascript'), '->getFormat() returns correct format when format have multiple mime-type (first)');
  89. $this->assertEquals('js', $request->getFormat('application/x-javascript'), '->getFormat() returns correct format when format have multiple mime-type');
  90. $this->assertEquals('js', $request->getFormat('text/javascript'), '->getFormat() returns correct format when format have multiple mime-type (last)');
  91. }
  92. /**
  93. * @covers Symfony\Component\HttpFoundation\Request::getUri
  94. */
  95. public function testGetUri()
  96. {
  97. $server = array();
  98. // Standard Request on non default PORT
  99. // http://hostname:8080/index.php/path/info?query=string
  100. $server['HTTP_HOST'] = 'hostname:8080';
  101. $server['SERVER_NAME'] = 'hostname';
  102. $server['SERVER_PORT'] = '8080';
  103. $server['QUERY_STRING'] = 'query=string';
  104. $server['REQUEST_URI'] = '/index.php/path/info?query=string';
  105. $server['SCRIPT_NAME'] = '/index.php';
  106. $server['PATH_INFO'] = '/path/info';
  107. $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
  108. $server['PHP_SELF'] = '/index_dev.php/path/info';
  109. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  110. $request = new Request();
  111. $request->initialize(null, null, null, null, null,$server);
  112. $this->assertEquals('http://hostname:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port');
  113. // Use std port number
  114. $server['HTTP_HOST'] = 'hostname';
  115. $server['SERVER_NAME'] = 'hostname';
  116. $server['SERVER_PORT'] = '80';
  117. $request->initialize(null, null, null, null, null, $server);
  118. $this->assertEquals('http://hostname/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port');
  119. // Without HOST HEADER
  120. unset($server['HTTP_HOST']);
  121. $server['SERVER_NAME'] = 'hostname';
  122. $server['SERVER_PORT'] = '80';
  123. $request->initialize(null, null, null, null, null, $server);
  124. $this->assertEquals('http://hostname/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER');
  125. // Request with URL REWRITING (hide index.php)
  126. // RewriteCond %{REQUEST_FILENAME} !-f
  127. // RewriteRule ^(.*)$ index.php [QSA,L]
  128. // http://hostname:8080/path/info?query=string
  129. $server = array();
  130. $server['HTTP_HOST'] = 'hostname:8080';
  131. $server['SERVER_NAME'] = 'hostname';
  132. $server['SERVER_PORT'] = '8080';
  133. $server['REDIRECT_QUERY_STRING'] = 'query=string';
  134. $server['REDIRECT_URL'] = '/path/info';
  135. $server['SCRIPT_NAME'] = '/index.php';
  136. $server['QUERY_STRING'] = 'query=string';
  137. $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
  138. $server['SCRIPT_NAME'] = '/index.php';
  139. $server['PHP_SELF'] = '/index.php';
  140. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  141. $request->initialize(null, null, null, null, null, $server);
  142. $this->assertEquals('http://hostname:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite');
  143. // Use std port number
  144. // http://hostname/path/info?query=string
  145. $server['HTTP_HOST'] = 'hostname';
  146. $server['SERVER_NAME'] = 'hostname';
  147. $server['SERVER_PORT'] = '80';
  148. $request->initialize(null, null, null, null, null, $server);
  149. $this->assertEquals('http://hostname/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port');
  150. // Without HOST HEADER
  151. unset($server['HTTP_HOST']);
  152. $server['SERVER_NAME'] = 'hostname';
  153. $server['SERVER_PORT'] = '80';
  154. $request->initialize(null, null, null, null, null, $server);
  155. $this->assertEquals('http://hostname/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER');
  156. }
  157. /**
  158. * @covers Symfony\Component\HttpFoundation\Request::getUriForPath
  159. */
  160. public function testGetUriForPath()
  161. {
  162. $request = Request::create('http://test.com/foo?bar=baz');
  163. $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path'));
  164. $request = Request::create('http://test.com:90/foo?bar=baz');
  165. $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path'));
  166. $request = Request::create('https://test.com/foo?bar=baz');
  167. $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path'));
  168. $request = Request::create('https://test.com:90/foo?bar=baz');
  169. $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path'));
  170. $server = array();
  171. // Standard Request on non default PORT
  172. // http://hostname:8080/index.php/path/info?query=string
  173. $server['HTTP_HOST'] = 'hostname:8080';
  174. $server['SERVER_NAME'] = 'hostname';
  175. $server['SERVER_PORT'] = '8080';
  176. $server['QUERY_STRING'] = 'query=string';
  177. $server['REQUEST_URI'] = '/index.php/path/info?query=string';
  178. $server['SCRIPT_NAME'] = '/index.php';
  179. $server['PATH_INFO'] = '/path/info';
  180. $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
  181. $server['PHP_SELF'] = '/index_dev.php/path/info';
  182. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  183. $request = new Request();
  184. $request->initialize(null, null, null, null, null,$server);
  185. $this->assertEquals('http://hostname:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port');
  186. // Use std port number
  187. $server['HTTP_HOST'] = 'hostname';
  188. $server['SERVER_NAME'] = 'hostname';
  189. $server['SERVER_PORT'] = '80';
  190. $request->initialize(null, null, null, null, null, $server);
  191. $this->assertEquals('http://hostname/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port');
  192. // Without HOST HEADER
  193. unset($server['HTTP_HOST']);
  194. $server['SERVER_NAME'] = 'hostname';
  195. $server['SERVER_PORT'] = '80';
  196. $request->initialize(null, null, null, null, null, $server);
  197. $this->assertEquals('http://hostname/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER');
  198. // Request with URL REWRITING (hide index.php)
  199. // RewriteCond %{REQUEST_FILENAME} !-f
  200. // RewriteRule ^(.*)$ index.php [QSA,L]
  201. // http://hostname:8080/path/info?query=string
  202. $server = array();
  203. $server['HTTP_HOST'] = 'hostname:8080';
  204. $server['SERVER_NAME'] = 'hostname';
  205. $server['SERVER_PORT'] = '8080';
  206. $server['REDIRECT_QUERY_STRING'] = 'query=string';
  207. $server['REDIRECT_URL'] = '/path/info';
  208. $server['SCRIPT_NAME'] = '/index.php';
  209. $server['QUERY_STRING'] = 'query=string';
  210. $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
  211. $server['SCRIPT_NAME'] = '/index.php';
  212. $server['PHP_SELF'] = '/index.php';
  213. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  214. $request->initialize(null, null, null, null, null, $server);
  215. $this->assertEquals('http://hostname:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite');
  216. // Use std port number
  217. // http://hostname/path/info?query=string
  218. $server['HTTP_HOST'] = 'hostname';
  219. $server['SERVER_NAME'] = 'hostname';
  220. $server['SERVER_PORT'] = '80';
  221. $request->initialize(null, null, null, null, null, $server);
  222. $this->assertEquals('http://hostname/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port');
  223. // Without HOST HEADER
  224. unset($server['HTTP_HOST']);
  225. $server['SERVER_NAME'] = 'hostname';
  226. $server['SERVER_PORT'] = '80';
  227. $request->initialize(null, null, null, null, null, $server);
  228. $this->assertEquals('http://hostname/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER');
  229. }
  230. /**
  231. * @covers Symfony\Component\HttpFoundation\Request::getQueryString
  232. */
  233. public function testGetQueryString()
  234. {
  235. $request = new Request();
  236. $request->server->set('QUERY_STRING', 'foo');
  237. $this->assertEquals('foo', $request->getQueryString(), '->getQueryString() works with valueless parameters');
  238. $request->server->set('QUERY_STRING', 'foo=');
  239. $this->assertEquals('foo=', $request->getQueryString(), '->getQueryString() includes a dangling equal sign');
  240. $request->server->set('QUERY_STRING', 'bar=&foo=bar');
  241. $this->assertEquals('bar=&foo=bar', $request->getQueryString(), '->getQueryString() works when empty parameters');
  242. $request->server->set('QUERY_STRING', 'foo=bar&bar=');
  243. $this->assertEquals('bar=&foo=bar', $request->getQueryString(), '->getQueryString() sorts keys alphabetically');
  244. $request->server->set('QUERY_STRING', 'him=John%20Doe&her=Jane+Doe');
  245. $this->assertEquals('her=Jane+Doe&him=John+Doe', $request->getQueryString(), '->getQueryString() normalizes encoding');
  246. $request->server->set('QUERY_STRING', 'foo[]=1&foo[]=2');
  247. $this->assertEquals('foo%5B%5D=1&foo%5B%5D=2', $request->getQueryString(), '->getQueryString() allows array notation');
  248. $request->server->set('QUERY_STRING', 'foo=1&foo=2');
  249. $this->assertEquals('foo=1&foo=2', $request->getQueryString(), '->getQueryString() allows repeated parameters');
  250. }
  251. /**
  252. * @covers Symfony\Component\HttpFoundation\Request::getHost
  253. */
  254. public function testGetHost()
  255. {
  256. $request = new Request();
  257. $request->initialize(array('foo' => 'bar'));
  258. $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized');
  259. $request->initialize(null, null, null, null, null, array('HTTP_HOST' => 'www.exemple.com'));
  260. $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from Host Header');
  261. // Host header with port number.
  262. $request->initialize(null, null, null, null, null, array('HTTP_HOST' => 'www.exemple.com:8080'));
  263. $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from Host Header with port number');
  264. // Server values.
  265. $request->initialize(null, null, null, null, null, array('SERVER_NAME' => 'www.exemple.com'));
  266. $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from server name');
  267. // X_FORWARDED_HOST.
  268. $request->initialize(null, null, null, null, null, array('HTTP_X_FORWARDED_HOST' => 'www.exemple.com'));
  269. $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from X_FORWARDED_HOST');
  270. // X_FORWARDED_HOST
  271. $request->initialize(null, null, null, null, null, array('HTTP_X_FORWARDED_HOST' => 'www.exemple.com, www.second.com'));
  272. $this->assertEquals('www.second.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST use last value');
  273. // X_FORWARDED_HOST with port number
  274. $request->initialize(null, null, null, null, null, array('HTTP_X_FORWARDED_HOST' => 'www.exemple.com, www.second.com:8080'));
  275. $this->assertEquals('www.second.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST with port number');
  276. $request->initialize(null, null, null, null, null, array('HTTP_HOST' => 'www.exemple.com', 'HTTP_X_FORWARDED_HOST' => 'www.forward.com'));
  277. $this->assertEquals('www.forward.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST has priority over Host');
  278. $request->initialize(null, null, null, null, null, array('SERVER_NAME' => 'www.exemple.com', 'HTTP_X_FORWARDED_HOST' => 'www.forward.com'));
  279. $this->assertEquals('www.forward.com', $request->getHost(), '->getHost() value from X_FORWARDED_HOST has priority over SERVER_NAME ');
  280. $request->initialize(null, null, null, null, null, array('SERVER_NAME' => 'www.exemple.com', 'HTTP_HOST' => 'www.host.com'));
  281. $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME ');
  282. }
  283. /**
  284. * @covers Symfony\Component\HttpFoundation\Request::setMethod
  285. * @covers Symfony\Component\HttpFoundation\Request::getMethod
  286. */
  287. public function testGetSetMethod()
  288. {
  289. $request = new Request();
  290. $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined');
  291. $request->setMethod('get');
  292. $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string');
  293. $request->setMethod('PURGE');
  294. $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one');
  295. $request->setMethod('POST');
  296. $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined');
  297. $request->setMethod('POST');
  298. $request->request->set('_method', 'purge');
  299. $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
  300. }
  301. public function testInitializeConvertsUploadedFiles()
  302. {
  303. $tmpFile = $this->createTempFile();
  304. $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
  305. $request = Request::create('', 'get', array(), array(), array('file' => array(
  306. 'name' => basename($tmpFile),
  307. 'type' => 'text/plain',
  308. 'tmp_name' => $tmpFile,
  309. 'error' => 0,
  310. 'size' => 100
  311. )));
  312. $this->assertEquals($file, $request->files->get('file'));
  313. }
  314. public function testInitializeDoesNotConvertEmptyUploadedFiles()
  315. {
  316. $request = Request::create('', 'get', array(), array(), array('file' => array(
  317. 'name' => '',
  318. 'type' => '',
  319. 'tmp_name' => '',
  320. 'error' => UPLOAD_ERR_NO_FILE,
  321. 'size' => 0
  322. )));
  323. $this->assertEquals(null, $request->files->get('file'));
  324. }
  325. public function testInitializeConvertsUploadedFilesWithPhpBug()
  326. {
  327. $tmpFile = $this->createTempFile();
  328. $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
  329. $request = Request::create('', 'get', array(), array(), array(
  330. 'child' => array(
  331. 'name' => array(
  332. 'file' => basename($tmpFile),
  333. ),
  334. 'type' => array(
  335. 'file' => 'text/plain',
  336. ),
  337. 'tmp_name' => array(
  338. 'file' => $tmpFile,
  339. ),
  340. 'error' => array(
  341. 'file' => 0,
  342. ),
  343. 'size' => array(
  344. 'file' => 100,
  345. ),
  346. )
  347. ));
  348. $files = $request->files->all();
  349. $this->assertEquals($file, $files['child']['file']);
  350. }
  351. public function testInitializeConvertsNestedUploadedFilesWithPhpBug()
  352. {
  353. $tmpFile = $this->createTempFile();
  354. $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0);
  355. $request = Request::create('', 'get', array(), array(), array(
  356. 'child' => array(
  357. 'name' => array(
  358. 'sub' => array('file' => basename($tmpFile))
  359. ),
  360. 'type' => array(
  361. 'sub' => array('file' => 'text/plain')
  362. ),
  363. 'tmp_name' => array(
  364. 'sub' => array('file' => $tmpFile)
  365. ),
  366. 'error' => array(
  367. 'sub' => array('file' => 0)
  368. ),
  369. 'size' => array(
  370. 'sub' => array('file' => 100)
  371. ),
  372. )
  373. ));
  374. $files = $request->files->all();
  375. $this->assertEquals($file, $files['child']['sub']['file']);
  376. }
  377. public function testGetContentWorksTwiceInDefaultMode()
  378. {
  379. $req = new Request;
  380. $this->assertEquals('', $req->getContent());
  381. $this->assertEquals('', $req->getContent());
  382. }
  383. public function testGetContentReturnsResource()
  384. {
  385. $req = new Request;
  386. $retval = $req->getContent(true);
  387. $this->assertType('resource', $retval);
  388. $this->assertEquals("", fread($retval, 1));
  389. $this->assertTrue(feof($retval));
  390. }
  391. /**
  392. * @expectedException LogicException
  393. * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
  394. */
  395. public function testGetContentCantBeCalledTwiceWithResources($first, $second)
  396. {
  397. $req = new Request;
  398. $req->getContent($first);
  399. $req->getContent($second);
  400. }
  401. public function getContentCantBeCalledTwiceWithResourcesProvider()
  402. {
  403. return array(
  404. 'Resource then fetch' => array(true, false),
  405. 'Resource then resource' => array(true, true),
  406. 'Fetch then resource' => array(false, true),
  407. );
  408. }
  409. protected function createTempFile()
  410. {
  411. return tempnam(sys_get_temp_dir(), 'FormTest');
  412. }
  413. }