RequestTest.php 40KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.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\SessionStorage\ArraySessionStorage;
  12. use Symfony\Component\HttpFoundation\Session;
  13. use Symfony\Component\HttpFoundation\Request;
  14. class RequestTest extends \PHPUnit_Framework_TestCase
  15. {
  16. /**
  17. * @covers Symfony\Component\HttpFoundation\Request::__construct
  18. */
  19. public function testConstructor()
  20. {
  21. $this->testInitialize();
  22. }
  23. /**
  24. * @covers Symfony\Component\HttpFoundation\Request::initialize
  25. */
  26. public function testInitialize()
  27. {
  28. $request = new Request();
  29. $request->initialize(array('foo' => 'bar'));
  30. $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument');
  31. $request->initialize(array(), array('foo' => 'bar'));
  32. $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument');
  33. $request->initialize(array(), array(), array('foo' => 'bar'));
  34. $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument');
  35. $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar'));
  36. $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its fourth argument');
  37. }
  38. /**
  39. * @covers Symfony\Component\HttpFoundation\Request::create
  40. */
  41. public function testCreate()
  42. {
  43. $request = Request::create('http://test.com/foo?bar=baz');
  44. $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
  45. $this->assertEquals('/foo', $request->getPathInfo());
  46. $this->assertEquals('bar=baz', $request->getQueryString());
  47. $this->assertEquals(80, $request->getPort());
  48. $this->assertEquals('test.com', $request->getHttpHost());
  49. $this->assertFalse($request->isSecure());
  50. $request = Request::create('https://test.com/foo?bar=baz');
  51. $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri());
  52. $this->assertEquals('/foo', $request->getPathInfo());
  53. $this->assertEquals('bar=baz', $request->getQueryString());
  54. $this->assertEquals(443, $request->getPort());
  55. $this->assertEquals('test.com', $request->getHttpHost());
  56. $this->assertTrue($request->isSecure());
  57. $request = Request::create('test.com:90/foo');
  58. $this->assertEquals('http://test.com:90/foo', $request->getUri());
  59. $this->assertEquals('/foo', $request->getPathInfo());
  60. $this->assertEquals('test.com', $request->getHost());
  61. $this->assertEquals('test.com:90', $request->getHttpHost());
  62. $this->assertEquals(90, $request->getPort());
  63. $this->assertFalse($request->isSecure());
  64. $request = Request::create('https://test.com:90/foo');
  65. $this->assertEquals('https://test.com:90/foo', $request->getUri());
  66. $this->assertEquals('/foo', $request->getPathInfo());
  67. $this->assertEquals('test.com', $request->getHost());
  68. $this->assertEquals('test.com:90', $request->getHttpHost());
  69. $this->assertEquals(90, $request->getPort());
  70. $this->assertTrue($request->isSecure());
  71. $request = Request::create('https://127.0.0.1:90/foo');
  72. $this->assertEquals('https://127.0.0.1:90/foo', $request->getUri());
  73. $this->assertEquals('/foo', $request->getPathInfo());
  74. $this->assertEquals('127.0.0.1', $request->getHost());
  75. $this->assertEquals('127.0.0.1:90', $request->getHttpHost());
  76. $this->assertEquals(90, $request->getPort());
  77. $this->assertTrue($request->isSecure());
  78. $request = Request::create('https://[::1]:90/foo');
  79. $this->assertEquals('https://[::1]:90/foo', $request->getUri());
  80. $this->assertEquals('/foo', $request->getPathInfo());
  81. $this->assertEquals('[::1]', $request->getHost());
  82. $this->assertEquals('[::1]:90', $request->getHttpHost());
  83. $this->assertEquals(90, $request->getPort());
  84. $this->assertTrue($request->isSecure());
  85. $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}';
  86. $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json);
  87. $this->assertEquals($json, $request->getContent());
  88. $this->assertFalse($request->isSecure());
  89. $request = Request::create('http://test.com');
  90. $this->assertEquals('http://test.com/', $request->getUri());
  91. $this->assertEquals('/', $request->getPathInfo());
  92. $this->assertEquals('', $request->getQueryString());
  93. $this->assertEquals(80, $request->getPort());
  94. $this->assertEquals('test.com', $request->getHttpHost());
  95. $this->assertFalse($request->isSecure());
  96. $request = Request::create('http://test.com:90/?test=1');
  97. $this->assertEquals('http://test.com:90/?test=1', $request->getUri());
  98. $this->assertEquals('/', $request->getPathInfo());
  99. $this->assertEquals('test=1', $request->getQueryString());
  100. $this->assertEquals(90, $request->getPort());
  101. $this->assertEquals('test.com:90', $request->getHttpHost());
  102. $this->assertFalse($request->isSecure());
  103. }
  104. /**
  105. * @covers Symfony\Component\HttpFoundation\Request::duplicate
  106. */
  107. public function testDuplicate()
  108. {
  109. $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar'));
  110. $dup = $request->duplicate();
  111. $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters');
  112. $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters');
  113. $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes');
  114. $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers');
  115. $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar'));
  116. $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided');
  117. $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided');
  118. $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided');
  119. $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided');
  120. }
  121. /**
  122. * @covers Symfony\Component\HttpFoundation\Request::getFormat
  123. * @covers Symfony\Component\HttpFoundation\Request::setFormat
  124. * @dataProvider getFormatToMimeTypeMapProvider
  125. */
  126. public function testGetFormatFromMimeType($format, $mimeTypes)
  127. {
  128. $request = new Request();
  129. foreach ($mimeTypes as $mime) {
  130. $this->assertEquals($format, $request->getFormat($mime));
  131. }
  132. $request->setFormat($format, $mimeTypes);
  133. foreach ($mimeTypes as $mime) {
  134. $this->assertEquals($format, $request->getFormat($mime));
  135. }
  136. }
  137. /**
  138. * @covers Symfony\Component\HttpFoundation\Request::getFormat
  139. */
  140. public function testGetFormatFromMimeTypeWithParameters()
  141. {
  142. $request = new Request();
  143. $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8'));
  144. }
  145. /**
  146. * @covers Symfony\Component\HttpFoundation\Request::getMimeType
  147. * @dataProvider getFormatToMimeTypeMapProvider
  148. */
  149. public function testGetMimeTypeFromFormat($format, $mimeTypes)
  150. {
  151. if (null !== $format) {
  152. $request = new Request();
  153. $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
  154. }
  155. }
  156. public function getFormatToMimeTypeMapProvider()
  157. {
  158. return array(
  159. array(null, array(null, 'unexistent-mime-type')),
  160. array('txt', array('text/plain')),
  161. array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')),
  162. array('css', array('text/css')),
  163. array('json', array('application/json', 'application/x-json')),
  164. array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
  165. array('rdf', array('application/rdf+xml')),
  166. array('atom',array('application/atom+xml')),
  167. );
  168. }
  169. /**
  170. * @covers Symfony\Component\HttpFoundation\Request::getUri
  171. */
  172. public function testGetUri()
  173. {
  174. $server = array();
  175. // Standard Request on non default PORT
  176. // http://hostname:8080/index.php/path/info?query=string
  177. $server['HTTP_HOST'] = 'hostname:8080';
  178. $server['SERVER_NAME'] = 'servername';
  179. $server['SERVER_PORT'] = '8080';
  180. $server['QUERY_STRING'] = 'query=string';
  181. $server['REQUEST_URI'] = '/index.php/path/info?query=string';
  182. $server['SCRIPT_NAME'] = '/index.php';
  183. $server['PATH_INFO'] = '/path/info';
  184. $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
  185. $server['PHP_SELF'] = '/index_dev.php/path/info';
  186. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  187. $request = new Request();
  188. $request->initialize(array(), array(), array(), array(), array(), $server);
  189. $this->assertEquals('http://hostname:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port');
  190. // Use std port number
  191. $server['HTTP_HOST'] = 'hostname';
  192. $server['SERVER_NAME'] = 'servername';
  193. $server['SERVER_PORT'] = '80';
  194. $request->initialize(array(), array(), array(), array(), array(), $server);
  195. $this->assertEquals('http://hostname/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port');
  196. // Without HOST HEADER
  197. unset($server['HTTP_HOST']);
  198. $server['SERVER_NAME'] = 'servername';
  199. $server['SERVER_PORT'] = '80';
  200. $request->initialize(array(), array(), array(), array(), array(), $server);
  201. $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER');
  202. // Request with URL REWRITING (hide index.php)
  203. // RewriteCond %{REQUEST_FILENAME} !-f
  204. // RewriteRule ^(.*)$ index.php [QSA,L]
  205. // http://hostname:8080/path/info?query=string
  206. $server = array();
  207. $server['HTTP_HOST'] = 'hostname:8080';
  208. $server['SERVER_NAME'] = 'servername';
  209. $server['SERVER_PORT'] = '8080';
  210. $server['REDIRECT_QUERY_STRING'] = 'query=string';
  211. $server['REDIRECT_URL'] = '/path/info';
  212. $server['SCRIPT_NAME'] = '/index.php';
  213. $server['QUERY_STRING'] = 'query=string';
  214. $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
  215. $server['SCRIPT_NAME'] = '/index.php';
  216. $server['PHP_SELF'] = '/index.php';
  217. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  218. $request->initialize(array(), array(), array(), array(), array(), $server);
  219. $this->assertEquals('http://hostname:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite');
  220. // Use std port number
  221. // http://hostname/path/info?query=string
  222. $server['HTTP_HOST'] = 'hostname';
  223. $server['SERVER_NAME'] = 'servername';
  224. $server['SERVER_PORT'] = '80';
  225. $request->initialize(array(), array(), array(), array(), array(), $server);
  226. $this->assertEquals('http://hostname/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port');
  227. // Without HOST HEADER
  228. unset($server['HTTP_HOST']);
  229. $server['SERVER_NAME'] = 'servername';
  230. $server['SERVER_PORT'] = '80';
  231. $request->initialize(array(), array(), array(), array(), array(), $server);
  232. $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER');
  233. }
  234. /**
  235. * @covers Symfony\Component\HttpFoundation\Request::getUriForPath
  236. */
  237. public function testGetUriForPath()
  238. {
  239. $request = Request::create('http://test.com/foo?bar=baz');
  240. $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path'));
  241. $request = Request::create('http://test.com:90/foo?bar=baz');
  242. $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path'));
  243. $request = Request::create('https://test.com/foo?bar=baz');
  244. $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path'));
  245. $request = Request::create('https://test.com:90/foo?bar=baz');
  246. $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path'));
  247. $server = array();
  248. // Standard Request on non default PORT
  249. // http://hostname:8080/index.php/path/info?query=string
  250. $server['HTTP_HOST'] = 'hostname:8080';
  251. $server['SERVER_NAME'] = 'servername';
  252. $server['SERVER_PORT'] = '8080';
  253. $server['QUERY_STRING'] = 'query=string';
  254. $server['REQUEST_URI'] = '/index.php/path/info?query=string';
  255. $server['SCRIPT_NAME'] = '/index.php';
  256. $server['PATH_INFO'] = '/path/info';
  257. $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
  258. $server['PHP_SELF'] = '/index_dev.php/path/info';
  259. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  260. $request = new Request();
  261. $request->initialize(array(), array(), array(), array(), array(),$server);
  262. $this->assertEquals('http://hostname:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port');
  263. // Use std port number
  264. $server['HTTP_HOST'] = 'hostname';
  265. $server['SERVER_NAME'] = 'servername';
  266. $server['SERVER_PORT'] = '80';
  267. $request->initialize(array(), array(), array(), array(), array(), $server);
  268. $this->assertEquals('http://hostname/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port');
  269. // Without HOST HEADER
  270. unset($server['HTTP_HOST']);
  271. $server['SERVER_NAME'] = 'servername';
  272. $server['SERVER_PORT'] = '80';
  273. $request->initialize(array(), array(), array(), array(), array(), $server);
  274. $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER');
  275. // Request with URL REWRITING (hide index.php)
  276. // RewriteCond %{REQUEST_FILENAME} !-f
  277. // RewriteRule ^(.*)$ index.php [QSA,L]
  278. // http://hostname:8080/path/info?query=string
  279. $server = array();
  280. $server['HTTP_HOST'] = 'hostname:8080';
  281. $server['SERVER_NAME'] = 'servername';
  282. $server['SERVER_PORT'] = '8080';
  283. $server['REDIRECT_QUERY_STRING'] = 'query=string';
  284. $server['REDIRECT_URL'] = '/path/info';
  285. $server['SCRIPT_NAME'] = '/index.php';
  286. $server['QUERY_STRING'] = 'query=string';
  287. $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
  288. $server['SCRIPT_NAME'] = '/index.php';
  289. $server['PHP_SELF'] = '/index.php';
  290. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  291. $request->initialize(array(), array(), array(), array(), array(), $server);
  292. $this->assertEquals('http://hostname:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite');
  293. // Use std port number
  294. // http://hostname/path/info?query=string
  295. $server['HTTP_HOST'] = 'hostname';
  296. $server['SERVER_NAME'] = 'servername';
  297. $server['SERVER_PORT'] = '80';
  298. $request->initialize(array(), array(), array(), array(), array(), $server);
  299. $this->assertEquals('http://hostname/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port');
  300. // Without HOST HEADER
  301. unset($server['HTTP_HOST']);
  302. $server['SERVER_NAME'] = 'servername';
  303. $server['SERVER_PORT'] = '80';
  304. $request->initialize(array(), array(), array(), array(), array(), $server);
  305. $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER');
  306. $this->assertEquals('servername', $request->getHttpHost());
  307. }
  308. /**
  309. * @covers Symfony\Component\HttpFoundation\Request::getQueryString
  310. */
  311. public function testGetQueryString()
  312. {
  313. $request = new Request();
  314. $request->server->set('QUERY_STRING', 'foo');
  315. $this->assertEquals('foo', $request->getQueryString(), '->getQueryString() works with valueless parameters');
  316. $request->server->set('QUERY_STRING', 'foo=');
  317. $this->assertEquals('foo=', $request->getQueryString(), '->getQueryString() includes a dangling equal sign');
  318. $request->server->set('QUERY_STRING', 'bar=&foo=bar');
  319. $this->assertEquals('bar=&foo=bar', $request->getQueryString(), '->getQueryString() works when empty parameters');
  320. $request->server->set('QUERY_STRING', 'foo=bar&bar=');
  321. $this->assertEquals('bar=&foo=bar', $request->getQueryString(), '->getQueryString() sorts keys alphabetically');
  322. $request->server->set('QUERY_STRING', 'him=John%20Doe&her=Jane+Doe');
  323. $this->assertEquals('her=Jane%2BDoe&him=John%20Doe', $request->getQueryString(), '->getQueryString() normalizes encoding');
  324. $request->server->set('QUERY_STRING', 'foo[]=1&foo[]=2');
  325. $this->assertEquals('foo%5B%5D=1&foo%5B%5D=2', $request->getQueryString(), '->getQueryString() allows array notation');
  326. $request->server->set('QUERY_STRING', 'foo=1&foo=2');
  327. $this->assertEquals('foo=1&foo=2', $request->getQueryString(), '->getQueryString() allows repeated parameters');
  328. }
  329. /**
  330. * @covers Symfony\Component\HttpFoundation\Request::getHost
  331. */
  332. public function testGetHost()
  333. {
  334. $request = new Request();
  335. $request->initialize(array('foo' => 'bar'));
  336. $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized');
  337. $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.exemple.com'));
  338. $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from Host Header');
  339. // Host header with port number
  340. $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.exemple.com:8080'));
  341. $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from Host Header with port number');
  342. // Server values
  343. $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.exemple.com'));
  344. $this->assertEquals('www.exemple.com', $request->getHost(), '->getHost() from server name');
  345. $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.exemple.com', 'HTTP_HOST' => 'www.host.com'));
  346. $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME ');
  347. }
  348. /**
  349. * @covers Symfony\Component\HttpFoundation\Request::setMethod
  350. * @covers Symfony\Component\HttpFoundation\Request::getMethod
  351. */
  352. public function testGetSetMethod()
  353. {
  354. $request = new Request();
  355. $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined');
  356. $request->setMethod('get');
  357. $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string');
  358. $request->setMethod('PURGE');
  359. $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one');
  360. $request->setMethod('POST');
  361. $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined');
  362. $request->setMethod('POST');
  363. $request->request->set('_method', 'purge');
  364. $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
  365. $request->setMethod('POST');
  366. $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
  367. $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST');
  368. $request = new Request();
  369. $request->setMethod('POST');
  370. $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
  371. $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST');
  372. }
  373. /**
  374. * @dataProvider testGetClientIpProvider
  375. */
  376. public function testGetClientIp($expected, $proxy, $remoteAddr, $httpForwardedFor, $trustedProxies)
  377. {
  378. $request = new Request();
  379. $server = array('REMOTE_ADDR' => $remoteAddr);
  380. if (null !== $httpForwardedFor) {
  381. $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor;
  382. }
  383. if ($proxy || $trustedProxies) {
  384. Request::setTrustedProxies(null === $trustedProxies ? array($remoteAddr) : $trustedProxies);
  385. }
  386. $request->initialize(array(), array(), array(), array(), array(), $server);
  387. $this->assertEquals($expected, $request->getClientIp($proxy));
  388. Request::setTrustedProxies(array());
  389. }
  390. public function testGetClientIpProvider()
  391. {
  392. return array(
  393. array('88.88.88.88', false, '88.88.88.88', null, null),
  394. array('127.0.0.1', false, '127.0.0.1', null, null),
  395. array('::1', false, '::1', null, null),
  396. array('127.0.0.1', false, '127.0.0.1', '88.88.88.88', null),
  397. array('88.88.88.88', true, '127.0.0.1', '88.88.88.88', null),
  398. array('2620:0:1cfe:face:b00c::3', true, '::1', '2620:0:1cfe:face:b00c::3', null),
  399. array('88.88.88.88', true, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', null),
  400. array('87.65.43.21', true, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')),
  401. array('87.65.43.21', false, '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')),
  402. );
  403. }
  404. public function testGetContentWorksTwiceInDefaultMode()
  405. {
  406. $req = new Request;
  407. $this->assertEquals('', $req->getContent());
  408. $this->assertEquals('', $req->getContent());
  409. }
  410. public function testGetContentReturnsResource()
  411. {
  412. $req = new Request;
  413. $retval = $req->getContent(true);
  414. $this->assertInternalType('resource', $retval);
  415. $this->assertEquals("", fread($retval, 1));
  416. $this->assertTrue(feof($retval));
  417. }
  418. /**
  419. * @expectedException LogicException
  420. * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
  421. */
  422. public function testGetContentCantBeCalledTwiceWithResources($first, $second)
  423. {
  424. $req = new Request;
  425. $req->getContent($first);
  426. $req->getContent($second);
  427. }
  428. public function getContentCantBeCalledTwiceWithResourcesProvider()
  429. {
  430. return array(
  431. 'Resource then fetch' => array(true, false),
  432. 'Resource then resource' => array(true, true),
  433. 'Fetch then resource' => array(false, true),
  434. );
  435. }
  436. public function testCreateFromGlobals()
  437. {
  438. $_GET['foo1'] = 'bar1';
  439. $_POST['foo2'] = 'bar2';
  440. $_COOKIE['foo3'] = 'bar3';
  441. $_FILES['foo4'] = array('bar4');
  442. $_SERVER['foo5'] = 'bar5';
  443. $request = Request::createFromGlobals();
  444. $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET');
  445. $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST');
  446. $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE');
  447. $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES');
  448. $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER');
  449. unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']);
  450. $_SERVER['REQUEST_METHOD'] = 'PUT';
  451. $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
  452. $request = RequestContentProxy::createFromGlobals();
  453. $this->assertEquals('PUT', $request->getMethod());
  454. $this->assertEquals('mycontent', $request->request->get('content'));
  455. unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']);
  456. $_POST['_method'] = 'PUT';
  457. $_POST['foo6'] = 'bar6';
  458. $_SERVER['REQUEST_METHOD'] = 'POST';
  459. $request = Request::createFromGlobals();
  460. $this->assertEquals('PUT', $request->getMethod());
  461. $this->assertEquals('bar6', $request->request->get('foo6'));
  462. unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']);
  463. }
  464. public function testOverrideGlobals()
  465. {
  466. $request = new Request();
  467. $request->initialize(array('foo' => 'bar'));
  468. // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it
  469. $server = $_SERVER;
  470. $request->overrideGlobals();
  471. $this->assertEquals(array('foo' => 'bar'), $_GET);
  472. $request->initialize(array(), array('foo' => 'bar'));
  473. $request->overrideGlobals();
  474. $this->assertEquals(array('foo' => 'bar'), $_POST);
  475. $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
  476. $request->headers->set('X_FORWARDED_PROTO', 'https');
  477. Request::setTrustedProxies(array('1.1.1.1'));
  478. $this->assertTrue($request->isSecure());
  479. Request::setTrustedProxies(array());
  480. $request->overrideGlobals();
  481. $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
  482. // restore initial $_SERVER array
  483. $_SERVER = $server;
  484. }
  485. public function testGetScriptName()
  486. {
  487. $request = new Request();
  488. $this->assertEquals('', $request->getScriptName());
  489. $server = array();
  490. $server['SCRIPT_NAME'] = '/index.php';
  491. $request->initialize(array(), array(), array(), array(), array(), $server);
  492. $this->assertEquals('/index.php', $request->getScriptName());
  493. $server = array();
  494. $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
  495. $request->initialize(array(), array(), array(), array(), array(), $server);
  496. $this->assertEquals('/frontend.php', $request->getScriptName());
  497. $server = array();
  498. $server['SCRIPT_NAME'] = '/index.php';
  499. $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
  500. $request->initialize(array(), array(), array(), array(), array(), $server);
  501. $this->assertEquals('/index.php', $request->getScriptName());
  502. }
  503. public function testGetBasePath()
  504. {
  505. $request = new Request();
  506. $this->assertEquals('', $request->getBasePath());
  507. $server = array();
  508. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  509. $request->initialize(array(), array(), array(), array(), array(), $server);
  510. $this->assertEquals('', $request->getBasePath());
  511. $server = array();
  512. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  513. $server['SCRIPT_NAME'] = '/index.php';
  514. $request->initialize(array(), array(), array(), array(), array(), $server);
  515. $this->assertEquals('', $request->getBasePath());
  516. $server = array();
  517. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  518. $server['PHP_SELF'] = '/index.php';
  519. $request->initialize(array(), array(), array(), array(), array(), $server);
  520. $this->assertEquals('', $request->getBasePath());
  521. $server = array();
  522. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  523. $server['ORIG_SCRIPT_NAME'] = '/index.php';
  524. $request->initialize(array(), array(), array(), array(), array(), $server);
  525. $this->assertEquals('', $request->getBasePath());
  526. }
  527. public function testGetPathInfo()
  528. {
  529. $request = new Request();
  530. $this->assertEquals('/', $request->getPathInfo());
  531. $server = array();
  532. $server['REQUEST_URI'] = '/path/info';
  533. $request->initialize(array(), array(), array(), array(), array(), $server);
  534. $this->assertEquals('/path/info', $request->getPathInfo());
  535. $server = array();
  536. $server['REQUEST_URI'] = '/path test/info';
  537. $request->initialize(array(), array(), array(), array(), array(), $server);
  538. $this->assertEquals('/path test/info', $request->getPathInfo());
  539. $server = array();
  540. $server['REQUEST_URI'] = '/path%20test/info';
  541. $request->initialize(array(), array(), array(), array(), array(), $server);
  542. $this->assertEquals('/path test/info', $request->getPathInfo());
  543. }
  544. public function testGetPreferredLanguage()
  545. {
  546. $request = new Request();
  547. $this->assertNull($request->getPreferredLanguage());
  548. $this->assertNull($request->getPreferredLanguage(array()));
  549. $this->assertEquals('fr', $request->getPreferredLanguage(array('fr')));
  550. $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en')));
  551. $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr')));
  552. $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr')));
  553. $request = new Request();
  554. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  555. $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us')));
  556. $request = new Request();
  557. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  558. $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
  559. }
  560. public function testIsXmlHttpRequest()
  561. {
  562. $request = new Request();
  563. $this->assertFalse($request->isXmlHttpRequest());
  564. $request->headers->set('X-Requested-With', 'XMLHttpRequest');
  565. $this->assertTrue($request->isXmlHttpRequest());
  566. $request->headers->remove('X-Requested-With');
  567. $this->assertFalse($request->isXmlHttpRequest());
  568. }
  569. public function testGetCharsets()
  570. {
  571. $request = new Request();
  572. $this->assertEquals(array(), $request->getCharsets());
  573. $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
  574. $this->assertEquals(array(), $request->getCharsets()); // testing caching
  575. $request = new Request();
  576. $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
  577. $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets());
  578. $request = new Request();
  579. $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7');
  580. $this->assertEquals(array('ISO-8859-1', 'utf-8', '*'), $request->getCharsets());
  581. }
  582. public function testGetAcceptableContentTypes()
  583. {
  584. $request = new Request();
  585. $this->assertEquals(array(), $request->getAcceptableContentTypes());
  586. $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
  587. $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching
  588. $request = new Request();
  589. $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
  590. $this->assertEquals(array('application/vnd.wap.wmlscriptc', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/xhtml+xml', 'text/html', 'multipart/mixed', '*/*'), $request->getAcceptableContentTypes());
  591. }
  592. public function testGetLanguages()
  593. {
  594. $request = new Request();
  595. $this->assertEquals(array(), $request->getLanguages());
  596. $request = new Request();
  597. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  598. $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());
  599. $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());
  600. $request = new Request();
  601. $request->headers->set('Accept-language', 'zh, en-us; q=0.6, en; q=0.8');
  602. $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test out of order qvalues
  603. $request = new Request();
  604. $request->headers->set('Accept-language', 'zh, en, en-us');
  605. $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test equal weighting without qvalues
  606. $request = new Request();
  607. $request->headers->set('Accept-language', 'zh; q=0.6, en, en-us; q=0.6');
  608. $this->assertEquals(array('en', 'zh', 'en_US'), $request->getLanguages()); // Test equal weighting with qvalues
  609. $request = new Request();
  610. $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6');
  611. $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages());
  612. }
  613. public function testGetRequestFormat()
  614. {
  615. $request = new Request();
  616. $this->assertEquals('html', $request->getRequestFormat());
  617. $request = new Request();
  618. $this->assertNull($request->getRequestFormat(null));
  619. $request = new Request();
  620. $request->setRequestFormat('foo');
  621. $this->assertEquals('foo', $request->getRequestFormat(null));
  622. }
  623. public function testHasSession()
  624. {
  625. $request = new Request;
  626. $this->assertFalse($request->hasSession());
  627. $request->setSession(new Session(new ArraySessionStorage()));
  628. $this->assertTrue($request->hasSession());
  629. }
  630. public function testHasPreviousSession()
  631. {
  632. $request = new Request;
  633. $this->assertFalse($request->hasPreviousSession());
  634. $request->cookies->set(session_name(), 'foo');
  635. $this->assertFalse($request->hasPreviousSession());
  636. $request->setSession(new Session(new ArraySessionStorage()));
  637. $this->assertTrue($request->hasPreviousSession());
  638. }
  639. public function testToString()
  640. {
  641. $request = new Request();
  642. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  643. $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $request->__toString());
  644. }
  645. /**
  646. * @dataProvider splitHttpAcceptHeaderData
  647. */
  648. public function testSplitHttpAcceptHeader($acceptHeader, $expected)
  649. {
  650. $request = new Request();
  651. $this->assertEquals($expected, $request->splitHttpAcceptHeader($acceptHeader));
  652. }
  653. public function splitHttpAcceptHeaderData()
  654. {
  655. return array(
  656. array(null, array()),
  657. array('text/html;q=0.8', array('text/html' => 0.8)),
  658. array('text/html;foo=bar;q=0.8 ', array('text/html;foo=bar' => 0.8)),
  659. array('text/html;charset=utf-8; q=0.8', array('text/html;charset=utf-8' => 0.8)),
  660. array('text/html,application/xml;q=0.9,*/*;charset=utf-8; q=0.8', array('text/html' => 1, 'application/xml' => 0.9, '*/*;charset=utf-8' => 0.8)),
  661. array('text/html,application/xhtml+xml;q=0.9,*/*;q=0.8; foo=bar', array('text/html' => 1, 'application/xhtml+xml' => 0.9, '*/*' => 0.8)),
  662. array('text/html,application/xhtml+xml;charset=utf-8;q=0.9; foo=bar,*/*', array('text/html' => 1, '*/*' => 1, 'application/xhtml+xml;charset=utf-8' => 0.9)),
  663. array('text/html,application/xhtml+xml', array('application/xhtml+xml' => 1, 'text/html' => 1)),
  664. );
  665. }
  666. public function testTrustedProxies()
  667. {
  668. $request = Request::create('http://example.com/');
  669. $request->server->set('REMOTE_ADDR', '3.3.3.3');
  670. $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2');
  671. $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080');
  672. $request->headers->set('X_FORWARDED_PROTO', 'https');
  673. $request->headers->set('X_FORWARDED_PORT', 443);
  674. $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4');
  675. $request->headers->set('X_MY_HOST', 'my.example.com');
  676. $request->headers->set('X_MY_PROTO', 'http');
  677. $request->headers->set('X_MY_PORT', 81);
  678. // no trusted proxies
  679. $this->assertEquals('3.3.3.3', $request->getClientIp());
  680. $this->assertEquals('example.com', $request->getHost());
  681. $this->assertEquals(80, $request->getPort());
  682. $this->assertFalse($request->isSecure());
  683. // trusted proxy via deprecated trustProxyData()
  684. Request::trustProxyData();
  685. $this->assertEquals('2.2.2.2', $request->getClientIp());
  686. $this->assertEquals('real.example.com', $request->getHost());
  687. $this->assertEquals(443, $request->getPort());
  688. $this->assertTrue($request->isSecure());
  689. // disabling proxy trusting
  690. Request::setTrustedProxies(array());
  691. $this->assertEquals('3.3.3.3', $request->getClientIp());
  692. $this->assertEquals('example.com', $request->getHost());
  693. $this->assertEquals(80, $request->getPort());
  694. $this->assertFalse($request->isSecure());
  695. // trusted proxy via setTrustedProxies()
  696. Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
  697. $this->assertEquals('1.1.1.1', $request->getClientIp());
  698. $this->assertEquals('real.example.com', $request->getHost());
  699. $this->assertEquals(443, $request->getPort());
  700. $this->assertTrue($request->isSecure());
  701. // custom header names
  702. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR');
  703. Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST');
  704. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT');
  705. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO');
  706. $this->assertEquals('4.4.4.4', $request->getClientIp());
  707. $this->assertEquals('my.example.com', $request->getHost());
  708. $this->assertEquals(81, $request->getPort());
  709. $this->assertFalse($request->isSecure());
  710. // disabling via empty header names
  711. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null);
  712. Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null);
  713. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null);
  714. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null);
  715. $this->assertEquals('3.3.3.3', $request->getClientIp());
  716. $this->assertEquals('example.com', $request->getHost());
  717. $this->assertEquals(80, $request->getPort());
  718. $this->assertFalse($request->isSecure());
  719. // reset
  720. Request::setTrustedProxies(array());
  721. }
  722. }
  723. class RequestContentProxy extends Request
  724. {
  725. public function getContent($asResource = false)
  726. {
  727. return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'));
  728. }
  729. }