RequestTest.php 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397
  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\Component\HttpFoundation\Tests;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Symfony\Component\HttpFoundation\Session\Session;
  15. use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
  16. class RequestTest extends TestCase
  17. {
  18. protected function tearDown()
  19. {
  20. Request::setTrustedProxies(array(), -1);
  21. Request::setTrustedHosts(array());
  22. }
  23. public function testInitialize()
  24. {
  25. $request = new Request();
  26. $request->initialize(array('foo' => 'bar'));
  27. $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument');
  28. $request->initialize(array(), array('foo' => 'bar'));
  29. $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument');
  30. $request->initialize(array(), array(), array('foo' => 'bar'));
  31. $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument');
  32. $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar'));
  33. $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its sixth argument');
  34. }
  35. public function testGetLocale()
  36. {
  37. $request = new Request();
  38. $request->setLocale('pl');
  39. $locale = $request->getLocale();
  40. $this->assertEquals('pl', $locale);
  41. }
  42. public function testGetUser()
  43. {
  44. $request = Request::create('http://user:password@test.com');
  45. $user = $request->getUser();
  46. $this->assertEquals('user', $user);
  47. }
  48. public function testGetPassword()
  49. {
  50. $request = Request::create('http://user:password@test.com');
  51. $password = $request->getPassword();
  52. $this->assertEquals('password', $password);
  53. }
  54. public function testIsNoCache()
  55. {
  56. $request = new Request();
  57. $isNoCache = $request->isNoCache();
  58. $this->assertFalse($isNoCache);
  59. }
  60. public function testGetContentType()
  61. {
  62. $request = new Request();
  63. $contentType = $request->getContentType();
  64. $this->assertNull($contentType);
  65. }
  66. public function testSetDefaultLocale()
  67. {
  68. $request = new Request();
  69. $request->setDefaultLocale('pl');
  70. $locale = $request->getLocale();
  71. $this->assertEquals('pl', $locale);
  72. }
  73. public function testCreate()
  74. {
  75. $request = Request::create('http://test.com/foo?bar=baz');
  76. $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
  77. $this->assertEquals('/foo', $request->getPathInfo());
  78. $this->assertEquals('bar=baz', $request->getQueryString());
  79. $this->assertEquals(80, $request->getPort());
  80. $this->assertEquals('test.com', $request->getHttpHost());
  81. $this->assertFalse($request->isSecure());
  82. $request = Request::create('http://test.com/foo', 'GET', array('bar' => 'baz'));
  83. $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
  84. $this->assertEquals('/foo', $request->getPathInfo());
  85. $this->assertEquals('bar=baz', $request->getQueryString());
  86. $this->assertEquals(80, $request->getPort());
  87. $this->assertEquals('test.com', $request->getHttpHost());
  88. $this->assertFalse($request->isSecure());
  89. $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz'));
  90. $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
  91. $this->assertEquals('/foo', $request->getPathInfo());
  92. $this->assertEquals('bar=baz', $request->getQueryString());
  93. $this->assertEquals(80, $request->getPort());
  94. $this->assertEquals('test.com', $request->getHttpHost());
  95. $this->assertFalse($request->isSecure());
  96. $request = Request::create('https://test.com/foo?bar=baz');
  97. $this->assertEquals('https://test.com/foo?bar=baz', $request->getUri());
  98. $this->assertEquals('/foo', $request->getPathInfo());
  99. $this->assertEquals('bar=baz', $request->getQueryString());
  100. $this->assertEquals(443, $request->getPort());
  101. $this->assertEquals('test.com', $request->getHttpHost());
  102. $this->assertTrue($request->isSecure());
  103. $request = Request::create('test.com:90/foo');
  104. $this->assertEquals('http://test.com:90/foo', $request->getUri());
  105. $this->assertEquals('/foo', $request->getPathInfo());
  106. $this->assertEquals('test.com', $request->getHost());
  107. $this->assertEquals('test.com:90', $request->getHttpHost());
  108. $this->assertEquals(90, $request->getPort());
  109. $this->assertFalse($request->isSecure());
  110. $request = Request::create('https://test.com:90/foo');
  111. $this->assertEquals('https://test.com:90/foo', $request->getUri());
  112. $this->assertEquals('/foo', $request->getPathInfo());
  113. $this->assertEquals('test.com', $request->getHost());
  114. $this->assertEquals('test.com:90', $request->getHttpHost());
  115. $this->assertEquals(90, $request->getPort());
  116. $this->assertTrue($request->isSecure());
  117. $request = Request::create('https://127.0.0.1:90/foo');
  118. $this->assertEquals('https://127.0.0.1:90/foo', $request->getUri());
  119. $this->assertEquals('/foo', $request->getPathInfo());
  120. $this->assertEquals('127.0.0.1', $request->getHost());
  121. $this->assertEquals('127.0.0.1:90', $request->getHttpHost());
  122. $this->assertEquals(90, $request->getPort());
  123. $this->assertTrue($request->isSecure());
  124. $request = Request::create('https://[::1]:90/foo');
  125. $this->assertEquals('https://[::1]:90/foo', $request->getUri());
  126. $this->assertEquals('/foo', $request->getPathInfo());
  127. $this->assertEquals('[::1]', $request->getHost());
  128. $this->assertEquals('[::1]:90', $request->getHttpHost());
  129. $this->assertEquals(90, $request->getPort());
  130. $this->assertTrue($request->isSecure());
  131. $request = Request::create('https://[::1]/foo');
  132. $this->assertEquals('https://[::1]/foo', $request->getUri());
  133. $this->assertEquals('/foo', $request->getPathInfo());
  134. $this->assertEquals('[::1]', $request->getHost());
  135. $this->assertEquals('[::1]', $request->getHttpHost());
  136. $this->assertEquals(443, $request->getPort());
  137. $this->assertTrue($request->isSecure());
  138. $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}';
  139. $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json);
  140. $this->assertEquals($json, $request->getContent());
  141. $this->assertFalse($request->isSecure());
  142. $request = Request::create('http://test.com');
  143. $this->assertEquals('http://test.com/', $request->getUri());
  144. $this->assertEquals('/', $request->getPathInfo());
  145. $this->assertEquals('', $request->getQueryString());
  146. $this->assertEquals(80, $request->getPort());
  147. $this->assertEquals('test.com', $request->getHttpHost());
  148. $this->assertFalse($request->isSecure());
  149. $request = Request::create('http://test.com?test=1');
  150. $this->assertEquals('http://test.com/?test=1', $request->getUri());
  151. $this->assertEquals('/', $request->getPathInfo());
  152. $this->assertEquals('test=1', $request->getQueryString());
  153. $this->assertEquals(80, $request->getPort());
  154. $this->assertEquals('test.com', $request->getHttpHost());
  155. $this->assertFalse($request->isSecure());
  156. $request = Request::create('http://test.com:90/?test=1');
  157. $this->assertEquals('http://test.com:90/?test=1', $request->getUri());
  158. $this->assertEquals('/', $request->getPathInfo());
  159. $this->assertEquals('test=1', $request->getQueryString());
  160. $this->assertEquals(90, $request->getPort());
  161. $this->assertEquals('test.com:90', $request->getHttpHost());
  162. $this->assertFalse($request->isSecure());
  163. $request = Request::create('http://username:password@test.com');
  164. $this->assertEquals('http://test.com/', $request->getUri());
  165. $this->assertEquals('/', $request->getPathInfo());
  166. $this->assertEquals('', $request->getQueryString());
  167. $this->assertEquals(80, $request->getPort());
  168. $this->assertEquals('test.com', $request->getHttpHost());
  169. $this->assertEquals('username', $request->getUser());
  170. $this->assertEquals('password', $request->getPassword());
  171. $this->assertFalse($request->isSecure());
  172. $request = Request::create('http://username@test.com');
  173. $this->assertEquals('http://test.com/', $request->getUri());
  174. $this->assertEquals('/', $request->getPathInfo());
  175. $this->assertEquals('', $request->getQueryString());
  176. $this->assertEquals(80, $request->getPort());
  177. $this->assertEquals('test.com', $request->getHttpHost());
  178. $this->assertEquals('username', $request->getUser());
  179. $this->assertSame('', $request->getPassword());
  180. $this->assertFalse($request->isSecure());
  181. $request = Request::create('http://test.com/?foo');
  182. $this->assertEquals('/?foo', $request->getRequestUri());
  183. $this->assertEquals(array('foo' => ''), $request->query->all());
  184. // assume rewrite rule: (.*) --> app/app.php; app/ is a symlink to a symfony web/ directory
  185. $request = Request::create('http://test.com/apparthotel-1234', 'GET', array(), array(), array(),
  186. array(
  187. 'DOCUMENT_ROOT' => '/var/www/www.test.com',
  188. 'SCRIPT_FILENAME' => '/var/www/www.test.com/app/app.php',
  189. 'SCRIPT_NAME' => '/app/app.php',
  190. 'PHP_SELF' => '/app/app.php/apparthotel-1234',
  191. ));
  192. $this->assertEquals('http://test.com/apparthotel-1234', $request->getUri());
  193. $this->assertEquals('/apparthotel-1234', $request->getPathInfo());
  194. $this->assertEquals('', $request->getQueryString());
  195. $this->assertEquals(80, $request->getPort());
  196. $this->assertEquals('test.com', $request->getHttpHost());
  197. $this->assertFalse($request->isSecure());
  198. // Fragment should not be included in the URI
  199. $request = Request::create('http://test.com/foo#bar');
  200. $this->assertEquals('http://test.com/foo', $request->getUri());
  201. }
  202. public function testCreateWithRequestUri()
  203. {
  204. $request = Request::create('http://test.com:80/foo');
  205. $request->server->set('REQUEST_URI', 'http://test.com:80/foo');
  206. $this->assertEquals('http://test.com/foo', $request->getUri());
  207. $this->assertEquals('/foo', $request->getPathInfo());
  208. $this->assertEquals('test.com', $request->getHost());
  209. $this->assertEquals('test.com', $request->getHttpHost());
  210. $this->assertEquals(80, $request->getPort());
  211. $this->assertFalse($request->isSecure());
  212. $request = Request::create('http://test.com:8080/foo');
  213. $request->server->set('REQUEST_URI', 'http://test.com:8080/foo');
  214. $this->assertEquals('http://test.com:8080/foo', $request->getUri());
  215. $this->assertEquals('/foo', $request->getPathInfo());
  216. $this->assertEquals('test.com', $request->getHost());
  217. $this->assertEquals('test.com:8080', $request->getHttpHost());
  218. $this->assertEquals(8080, $request->getPort());
  219. $this->assertFalse($request->isSecure());
  220. $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz'));
  221. $request->server->set('REQUEST_URI', 'http://test.com/foo?bar=foo');
  222. $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri());
  223. $this->assertEquals('/foo', $request->getPathInfo());
  224. $this->assertEquals('bar=baz', $request->getQueryString());
  225. $this->assertEquals('test.com', $request->getHost());
  226. $this->assertEquals('test.com', $request->getHttpHost());
  227. $this->assertEquals(80, $request->getPort());
  228. $this->assertFalse($request->isSecure());
  229. $request = Request::create('https://test.com:443/foo');
  230. $request->server->set('REQUEST_URI', 'https://test.com:443/foo');
  231. $this->assertEquals('https://test.com/foo', $request->getUri());
  232. $this->assertEquals('/foo', $request->getPathInfo());
  233. $this->assertEquals('test.com', $request->getHost());
  234. $this->assertEquals('test.com', $request->getHttpHost());
  235. $this->assertEquals(443, $request->getPort());
  236. $this->assertTrue($request->isSecure());
  237. // Fragment should not be included in the URI
  238. $request = Request::create('http://test.com/foo#bar');
  239. $request->server->set('REQUEST_URI', 'http://test.com/foo#bar');
  240. $this->assertEquals('http://test.com/foo', $request->getUri());
  241. }
  242. public function testCreateCheckPrecedence()
  243. {
  244. // server is used by default
  245. $request = Request::create('/', 'DELETE', array(), array(), array(), array(
  246. 'HTTP_HOST' => 'example.com',
  247. 'HTTPS' => 'on',
  248. 'SERVER_PORT' => 443,
  249. 'PHP_AUTH_USER' => 'fabien',
  250. 'PHP_AUTH_PW' => 'pa$$',
  251. 'QUERY_STRING' => 'foo=bar',
  252. 'CONTENT_TYPE' => 'application/json',
  253. ));
  254. $this->assertEquals('example.com', $request->getHost());
  255. $this->assertEquals(443, $request->getPort());
  256. $this->assertTrue($request->isSecure());
  257. $this->assertEquals('fabien', $request->getUser());
  258. $this->assertEquals('pa$$', $request->getPassword());
  259. $this->assertEquals('', $request->getQueryString());
  260. $this->assertEquals('application/json', $request->headers->get('CONTENT_TYPE'));
  261. // URI has precedence over server
  262. $request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', array(), array(), array(), array(
  263. 'HTTP_HOST' => 'example.com',
  264. 'HTTPS' => 'on',
  265. 'SERVER_PORT' => 443,
  266. ));
  267. $this->assertEquals('example.net', $request->getHost());
  268. $this->assertEquals(8080, $request->getPort());
  269. $this->assertFalse($request->isSecure());
  270. $this->assertEquals('thomas', $request->getUser());
  271. $this->assertEquals('pokemon', $request->getPassword());
  272. $this->assertEquals('foo=bar', $request->getQueryString());
  273. }
  274. public function testDuplicate()
  275. {
  276. $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar'));
  277. $dup = $request->duplicate();
  278. $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters');
  279. $this->assertEquals($request->request->all(), $dup->request->all(), '->duplicate() duplicates a request an copy the current request parameters');
  280. $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes');
  281. $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers');
  282. $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar'));
  283. $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided');
  284. $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided');
  285. $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided');
  286. $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided');
  287. }
  288. public function testDuplicateWithFormat()
  289. {
  290. $request = new Request(array(), array(), array('_format' => 'json'));
  291. $dup = $request->duplicate();
  292. $this->assertEquals('json', $dup->getRequestFormat());
  293. $this->assertEquals('json', $dup->attributes->get('_format'));
  294. $request = new Request();
  295. $request->setRequestFormat('xml');
  296. $dup = $request->duplicate();
  297. $this->assertEquals('xml', $dup->getRequestFormat());
  298. }
  299. /**
  300. * @dataProvider getFormatToMimeTypeMapProviderWithAdditionalNullFormat
  301. */
  302. public function testGetFormatFromMimeType($format, $mimeTypes)
  303. {
  304. $request = new Request();
  305. foreach ($mimeTypes as $mime) {
  306. $this->assertEquals($format, $request->getFormat($mime));
  307. }
  308. $request->setFormat($format, $mimeTypes);
  309. foreach ($mimeTypes as $mime) {
  310. $this->assertEquals($format, $request->getFormat($mime));
  311. if (null !== $format) {
  312. $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
  313. }
  314. }
  315. }
  316. public function getFormatToMimeTypeMapProviderWithAdditionalNullFormat()
  317. {
  318. return array_merge(
  319. array(array(null, array(null, 'unexistent-mime-type'))),
  320. $this->getFormatToMimeTypeMapProvider()
  321. );
  322. }
  323. public function testGetFormatFromMimeTypeWithParameters()
  324. {
  325. $request = new Request();
  326. $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8'));
  327. $this->assertEquals('json', $request->getFormat('application/json;charset=utf-8'));
  328. $this->assertEquals('json', $request->getFormat('application/json ; charset=utf-8'));
  329. $this->assertEquals('json', $request->getFormat('application/json ;charset=utf-8'));
  330. }
  331. /**
  332. * @dataProvider getFormatToMimeTypeMapProvider
  333. */
  334. public function testGetMimeTypeFromFormat($format, $mimeTypes)
  335. {
  336. $request = new Request();
  337. $this->assertEquals($mimeTypes[0], $request->getMimeType($format));
  338. }
  339. /**
  340. * @dataProvider getFormatToMimeTypeMapProvider
  341. */
  342. public function testGetMimeTypesFromFormat($format, $mimeTypes)
  343. {
  344. $this->assertEquals($mimeTypes, Request::getMimeTypes($format));
  345. }
  346. public function testGetMimeTypesFromInexistentFormat()
  347. {
  348. $request = new Request();
  349. $this->assertNull($request->getMimeType('foo'));
  350. $this->assertEquals(array(), Request::getMimeTypes('foo'));
  351. }
  352. public function testGetFormatWithCustomMimeType()
  353. {
  354. $request = new Request();
  355. $request->setFormat('custom', 'application/vnd.foo.api;myversion=2.3');
  356. $this->assertEquals('custom', $request->getFormat('application/vnd.foo.api;myversion=2.3'));
  357. }
  358. public function getFormatToMimeTypeMapProvider()
  359. {
  360. return array(
  361. array('txt', array('text/plain')),
  362. array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')),
  363. array('css', array('text/css')),
  364. array('json', array('application/json', 'application/x-json')),
  365. array('jsonld', array('application/ld+json')),
  366. array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
  367. array('rdf', array('application/rdf+xml')),
  368. array('atom', array('application/atom+xml')),
  369. );
  370. }
  371. public function testGetUri()
  372. {
  373. $server = array();
  374. // Standard Request on non default PORT
  375. // http://host:8080/index.php/path/info?query=string
  376. $server['HTTP_HOST'] = 'host:8080';
  377. $server['SERVER_NAME'] = 'servername';
  378. $server['SERVER_PORT'] = '8080';
  379. $server['QUERY_STRING'] = 'query=string';
  380. $server['REQUEST_URI'] = '/index.php/path/info?query=string';
  381. $server['SCRIPT_NAME'] = '/index.php';
  382. $server['PATH_INFO'] = '/path/info';
  383. $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
  384. $server['PHP_SELF'] = '/index_dev.php/path/info';
  385. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  386. $request = new Request();
  387. $request->initialize(array(), array(), array(), array(), array(), $server);
  388. $this->assertEquals('http://host:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port');
  389. // Use std port number
  390. $server['HTTP_HOST'] = 'host';
  391. $server['SERVER_NAME'] = 'servername';
  392. $server['SERVER_PORT'] = '80';
  393. $request->initialize(array(), array(), array(), array(), array(), $server);
  394. $this->assertEquals('http://host/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port');
  395. // Without HOST HEADER
  396. unset($server['HTTP_HOST']);
  397. $server['SERVER_NAME'] = 'servername';
  398. $server['SERVER_PORT'] = '80';
  399. $request->initialize(array(), array(), array(), array(), array(), $server);
  400. $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER');
  401. // Request with URL REWRITING (hide index.php)
  402. // RewriteCond %{REQUEST_FILENAME} !-f
  403. // RewriteRule ^(.*)$ index.php [QSA,L]
  404. // http://host:8080/path/info?query=string
  405. $server = array();
  406. $server['HTTP_HOST'] = 'host:8080';
  407. $server['SERVER_NAME'] = 'servername';
  408. $server['SERVER_PORT'] = '8080';
  409. $server['REDIRECT_QUERY_STRING'] = 'query=string';
  410. $server['REDIRECT_URL'] = '/path/info';
  411. $server['SCRIPT_NAME'] = '/index.php';
  412. $server['QUERY_STRING'] = 'query=string';
  413. $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
  414. $server['SCRIPT_NAME'] = '/index.php';
  415. $server['PHP_SELF'] = '/index.php';
  416. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  417. $request->initialize(array(), array(), array(), array(), array(), $server);
  418. $this->assertEquals('http://host:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite');
  419. // Use std port number
  420. // http://host/path/info?query=string
  421. $server['HTTP_HOST'] = 'host';
  422. $server['SERVER_NAME'] = 'servername';
  423. $server['SERVER_PORT'] = '80';
  424. $request->initialize(array(), array(), array(), array(), array(), $server);
  425. $this->assertEquals('http://host/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port');
  426. // Without HOST HEADER
  427. unset($server['HTTP_HOST']);
  428. $server['SERVER_NAME'] = 'servername';
  429. $server['SERVER_PORT'] = '80';
  430. $request->initialize(array(), array(), array(), array(), array(), $server);
  431. $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER');
  432. // With encoded characters
  433. $server = array(
  434. 'HTTP_HOST' => 'host:8080',
  435. 'SERVER_NAME' => 'servername',
  436. 'SERVER_PORT' => '8080',
  437. 'QUERY_STRING' => 'query=string',
  438. 'REQUEST_URI' => '/ba%20se/index_dev.php/foo%20bar/in+fo?query=string',
  439. 'SCRIPT_NAME' => '/ba se/index_dev.php',
  440. 'PATH_TRANSLATED' => 'redirect:/index.php/foo bar/in+fo',
  441. 'PHP_SELF' => '/ba se/index_dev.php/path/info',
  442. 'SCRIPT_FILENAME' => '/some/where/ba se/index_dev.php',
  443. );
  444. $request->initialize(array(), array(), array(), array(), array(), $server);
  445. $this->assertEquals(
  446. 'http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string',
  447. $request->getUri()
  448. );
  449. // with user info
  450. $server['PHP_AUTH_USER'] = 'fabien';
  451. $request->initialize(array(), array(), array(), array(), array(), $server);
  452. $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri());
  453. $server['PHP_AUTH_PW'] = 'symfony';
  454. $request->initialize(array(), array(), array(), array(), array(), $server);
  455. $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri());
  456. }
  457. public function testGetUriForPath()
  458. {
  459. $request = Request::create('http://test.com/foo?bar=baz');
  460. $this->assertEquals('http://test.com/some/path', $request->getUriForPath('/some/path'));
  461. $request = Request::create('http://test.com:90/foo?bar=baz');
  462. $this->assertEquals('http://test.com:90/some/path', $request->getUriForPath('/some/path'));
  463. $request = Request::create('https://test.com/foo?bar=baz');
  464. $this->assertEquals('https://test.com/some/path', $request->getUriForPath('/some/path'));
  465. $request = Request::create('https://test.com:90/foo?bar=baz');
  466. $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path'));
  467. $server = array();
  468. // Standard Request on non default PORT
  469. // http://host:8080/index.php/path/info?query=string
  470. $server['HTTP_HOST'] = 'host:8080';
  471. $server['SERVER_NAME'] = 'servername';
  472. $server['SERVER_PORT'] = '8080';
  473. $server['QUERY_STRING'] = 'query=string';
  474. $server['REQUEST_URI'] = '/index.php/path/info?query=string';
  475. $server['SCRIPT_NAME'] = '/index.php';
  476. $server['PATH_INFO'] = '/path/info';
  477. $server['PATH_TRANSLATED'] = 'redirect:/index.php/path/info';
  478. $server['PHP_SELF'] = '/index_dev.php/path/info';
  479. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  480. $request = new Request();
  481. $request->initialize(array(), array(), array(), array(), array(), $server);
  482. $this->assertEquals('http://host:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port');
  483. // Use std port number
  484. $server['HTTP_HOST'] = 'host';
  485. $server['SERVER_NAME'] = 'servername';
  486. $server['SERVER_PORT'] = '80';
  487. $request->initialize(array(), array(), array(), array(), array(), $server);
  488. $this->assertEquals('http://host/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port');
  489. // Without HOST HEADER
  490. unset($server['HTTP_HOST']);
  491. $server['SERVER_NAME'] = 'servername';
  492. $server['SERVER_PORT'] = '80';
  493. $request->initialize(array(), array(), array(), array(), array(), $server);
  494. $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER');
  495. // Request with URL REWRITING (hide index.php)
  496. // RewriteCond %{REQUEST_FILENAME} !-f
  497. // RewriteRule ^(.*)$ index.php [QSA,L]
  498. // http://host:8080/path/info?query=string
  499. $server = array();
  500. $server['HTTP_HOST'] = 'host:8080';
  501. $server['SERVER_NAME'] = 'servername';
  502. $server['SERVER_PORT'] = '8080';
  503. $server['REDIRECT_QUERY_STRING'] = 'query=string';
  504. $server['REDIRECT_URL'] = '/path/info';
  505. $server['SCRIPT_NAME'] = '/index.php';
  506. $server['QUERY_STRING'] = 'query=string';
  507. $server['REQUEST_URI'] = '/path/info?toto=test&1=1';
  508. $server['SCRIPT_NAME'] = '/index.php';
  509. $server['PHP_SELF'] = '/index.php';
  510. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  511. $request->initialize(array(), array(), array(), array(), array(), $server);
  512. $this->assertEquals('http://host:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite');
  513. // Use std port number
  514. // http://host/path/info?query=string
  515. $server['HTTP_HOST'] = 'host';
  516. $server['SERVER_NAME'] = 'servername';
  517. $server['SERVER_PORT'] = '80';
  518. $request->initialize(array(), array(), array(), array(), array(), $server);
  519. $this->assertEquals('http://host/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port');
  520. // Without HOST HEADER
  521. unset($server['HTTP_HOST']);
  522. $server['SERVER_NAME'] = 'servername';
  523. $server['SERVER_PORT'] = '80';
  524. $request->initialize(array(), array(), array(), array(), array(), $server);
  525. $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER');
  526. $this->assertEquals('servername', $request->getHttpHost());
  527. // with user info
  528. $server['PHP_AUTH_USER'] = 'fabien';
  529. $request->initialize(array(), array(), array(), array(), array(), $server);
  530. $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'));
  531. $server['PHP_AUTH_PW'] = 'symfony';
  532. $request->initialize(array(), array(), array(), array(), array(), $server);
  533. $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'));
  534. }
  535. /**
  536. * @dataProvider getRelativeUriForPathData()
  537. */
  538. public function testGetRelativeUriForPath($expected, $pathinfo, $path)
  539. {
  540. $this->assertEquals($expected, Request::create($pathinfo)->getRelativeUriForPath($path));
  541. }
  542. public function getRelativeUriForPathData()
  543. {
  544. return array(
  545. array('me.png', '/foo', '/me.png'),
  546. array('../me.png', '/foo/bar', '/me.png'),
  547. array('me.png', '/foo/bar', '/foo/me.png'),
  548. array('../baz/me.png', '/foo/bar/b', '/foo/baz/me.png'),
  549. array('../../fooz/baz/me.png', '/foo/bar/b', '/fooz/baz/me.png'),
  550. array('baz/me.png', '/foo/bar/b', 'baz/me.png'),
  551. );
  552. }
  553. public function testGetUserInfo()
  554. {
  555. $request = new Request();
  556. $server = array('PHP_AUTH_USER' => 'fabien');
  557. $request->initialize(array(), array(), array(), array(), array(), $server);
  558. $this->assertEquals('fabien', $request->getUserInfo());
  559. $server['PHP_AUTH_USER'] = '0';
  560. $request->initialize(array(), array(), array(), array(), array(), $server);
  561. $this->assertEquals('0', $request->getUserInfo());
  562. $server['PHP_AUTH_PW'] = '0';
  563. $request->initialize(array(), array(), array(), array(), array(), $server);
  564. $this->assertEquals('0:0', $request->getUserInfo());
  565. }
  566. public function testGetSchemeAndHttpHost()
  567. {
  568. $request = new Request();
  569. $server = array();
  570. $server['SERVER_NAME'] = 'servername';
  571. $server['SERVER_PORT'] = '90';
  572. $request->initialize(array(), array(), array(), array(), array(), $server);
  573. $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
  574. $server['PHP_AUTH_USER'] = 'fabien';
  575. $request->initialize(array(), array(), array(), array(), array(), $server);
  576. $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
  577. $server['PHP_AUTH_USER'] = '0';
  578. $request->initialize(array(), array(), array(), array(), array(), $server);
  579. $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
  580. $server['PHP_AUTH_PW'] = '0';
  581. $request->initialize(array(), array(), array(), array(), array(), $server);
  582. $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost());
  583. }
  584. /**
  585. * @dataProvider getQueryStringNormalizationData
  586. */
  587. public function testGetQueryString($query, $expectedQuery, $msg)
  588. {
  589. $request = new Request();
  590. $request->server->set('QUERY_STRING', $query);
  591. $this->assertSame($expectedQuery, $request->getQueryString(), $msg);
  592. }
  593. public function getQueryStringNormalizationData()
  594. {
  595. return array(
  596. array('foo', 'foo', 'works with valueless parameters'),
  597. array('foo=', 'foo=', 'includes a dangling equal sign'),
  598. array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'),
  599. array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'),
  600. // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded).
  601. // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str.
  602. array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'),
  603. array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'),
  604. array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'),
  605. array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'),
  606. array('0', '0', 'allows "0"'),
  607. array('Jane Doe&John%20Doe', 'Jane%20Doe&John%20Doe', 'normalizes encoding in keys'),
  608. array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'),
  609. array('foo=bar&&&test&&', 'foo=bar&test', 'removes unneeded delimiters'),
  610. array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'),
  611. // Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway.
  612. // PHP also does not include them when building _GET.
  613. array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'),
  614. );
  615. }
  616. public function testGetQueryStringReturnsNull()
  617. {
  618. $request = new Request();
  619. $this->assertNull($request->getQueryString(), '->getQueryString() returns null for non-existent query string');
  620. $request->server->set('QUERY_STRING', '');
  621. $this->assertNull($request->getQueryString(), '->getQueryString() returns null for empty query string');
  622. }
  623. public function testGetHost()
  624. {
  625. $request = new Request();
  626. $request->initialize(array('foo' => 'bar'));
  627. $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized');
  628. $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com'));
  629. $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header');
  630. // Host header with port number
  631. $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com:8080'));
  632. $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header with port number');
  633. // Server values
  634. $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com'));
  635. $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from server name');
  636. $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com', 'HTTP_HOST' => 'www.host.com'));
  637. $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME ');
  638. }
  639. public function testGetPort()
  640. {
  641. $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
  642. 'HTTP_X_FORWARDED_PROTO' => 'https',
  643. 'HTTP_X_FORWARDED_PORT' => '443',
  644. ));
  645. $port = $request->getPort();
  646. $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.');
  647. Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL);
  648. $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
  649. 'HTTP_X_FORWARDED_PROTO' => 'https',
  650. 'HTTP_X_FORWARDED_PORT' => '8443',
  651. ));
  652. $this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.');
  653. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  654. $this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.');
  655. $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
  656. 'HTTP_X_FORWARDED_PROTO' => 'https',
  657. ));
  658. $this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.');
  659. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  660. $this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.');
  661. $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
  662. 'HTTP_X_FORWARDED_PROTO' => 'http',
  663. ));
  664. $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.');
  665. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  666. $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.');
  667. $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
  668. 'HTTP_X_FORWARDED_PROTO' => 'On',
  669. ));
  670. $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.');
  671. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  672. $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.');
  673. $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
  674. 'HTTP_X_FORWARDED_PROTO' => '1',
  675. ));
  676. $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.');
  677. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  678. $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.');
  679. $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
  680. 'HTTP_X_FORWARDED_PROTO' => 'something-else',
  681. ));
  682. $port = $request->getPort();
  683. $this->assertEquals(80, $port, 'With only PROTO set and value is not recognized, getPort() defaults to 80.');
  684. }
  685. /**
  686. * @expectedException \RuntimeException
  687. */
  688. public function testGetHostWithFakeHttpHostValue()
  689. {
  690. $request = new Request();
  691. $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string'));
  692. $request->getHost();
  693. }
  694. public function testGetSetMethod()
  695. {
  696. $request = new Request();
  697. $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns GET if no method is defined');
  698. $request->setMethod('get');
  699. $this->assertEquals('GET', $request->getMethod(), '->getMethod() returns an uppercased string');
  700. $request->setMethod('PURGE');
  701. $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method even if it is not a standard one');
  702. $request->setMethod('POST');
  703. $this->assertEquals('POST', $request->getMethod(), '->getMethod() returns the method POST if no _method is defined');
  704. $request->setMethod('POST');
  705. $request->request->set('_method', 'purge');
  706. $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');
  707. $request = new Request();
  708. $request->setMethod('POST');
  709. $request->request->set('_method', 'purge');
  710. $this->assertFalse(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be disabled by default');
  711. Request::enableHttpMethodParameterOverride();
  712. $this->assertTrue(Request::getHttpMethodParameterOverride(), 'httpMethodParameterOverride should be enabled now but it is not');
  713. $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
  714. $this->disableHttpMethodParameterOverride();
  715. $request = new Request();
  716. $request->setMethod('POST');
  717. $request->query->set('_method', 'purge');
  718. $this->assertEquals('POST', $request->getMethod(), '->getMethod() does not return the method from _method if defined and POST but support not enabled');
  719. $request = new Request();
  720. $request->setMethod('POST');
  721. $request->query->set('_method', 'purge');
  722. Request::enableHttpMethodParameterOverride();
  723. $this->assertEquals('PURGE', $request->getMethod(), '->getMethod() returns the method from _method if defined and POST');
  724. $this->disableHttpMethodParameterOverride();
  725. $request = new Request();
  726. $request->setMethod('POST');
  727. $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
  728. $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override even though _method is set if defined and POST');
  729. $request = new Request();
  730. $request->setMethod('POST');
  731. $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete');
  732. $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST');
  733. $request = new Request();
  734. $request->setMethod('POST');
  735. $request->query->set('_method', array('delete', 'patch'));
  736. $this->assertSame('POST', $request->getMethod(), '->getMethod() returns the request method if invalid type is defined in query');
  737. }
  738. /**
  739. * @dataProvider getClientIpsProvider
  740. */
  741. public function testGetClientIp($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
  742. {
  743. $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
  744. $this->assertEquals($expected[0], $request->getClientIp());
  745. }
  746. /**
  747. * @dataProvider getClientIpsProvider
  748. */
  749. public function testGetClientIps($expected, $remoteAddr, $httpForwardedFor, $trustedProxies)
  750. {
  751. $request = $this->getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies);
  752. $this->assertEquals($expected, $request->getClientIps());
  753. }
  754. /**
  755. * @dataProvider getClientIpsForwardedProvider
  756. */
  757. public function testGetClientIpsForwarded($expected, $remoteAddr, $httpForwarded, $trustedProxies)
  758. {
  759. $request = $this->getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies);
  760. $this->assertEquals($expected, $request->getClientIps());
  761. }
  762. public function getClientIpsForwardedProvider()
  763. {
  764. // $expected $remoteAddr $httpForwarded $trustedProxies
  765. return array(
  766. array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', null),
  767. array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')),
  768. array(array('88.88.88.88'), '127.0.0.1', 'for="88.88.88.88:80"', array('127.0.0.1')),
  769. array(array('192.0.2.60'), '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', array('::1')),
  770. array(array('2620:0:1cfe:face:b00c::3', '192.0.2.43'), '::1', 'for=192.0.2.43, for=2620:0:1cfe:face:b00c::3', array('::1')),
  771. array(array('2001:db8:cafe::17'), '::1', 'for="[2001:db8:cafe::17]:4711', array('::1')),
  772. );
  773. }
  774. public function getClientIpsProvider()
  775. {
  776. // $expected $remoteAddr $httpForwardedFor $trustedProxies
  777. return array(
  778. // simple IPv4
  779. array(array('88.88.88.88'), '88.88.88.88', null, null),
  780. // trust the IPv4 remote addr
  781. array(array('88.88.88.88'), '88.88.88.88', null, array('88.88.88.88')),
  782. // simple IPv6
  783. array(array('::1'), '::1', null, null),
  784. // trust the IPv6 remote addr
  785. array(array('::1'), '::1', null, array('::1')),
  786. // forwarded for with remote IPv4 addr not trusted
  787. array(array('127.0.0.1'), '127.0.0.1', '88.88.88.88', null),
  788. // forwarded for with remote IPv4 addr trusted + comma
  789. array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88,', array('127.0.0.1')),
  790. // forwarded for with remote IPv4 and all FF addrs trusted
  791. array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1', '88.88.88.88')),
  792. // forwarded for with remote IPv4 range trusted
  793. array(array('88.88.88.88'), '123.45.67.89', '88.88.88.88', array('123.45.67.0/24')),
  794. // forwarded for with remote IPv6 addr not trusted
  795. array(array('1620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', null),
  796. // forwarded for with remote IPv6 addr trusted
  797. array(array('2620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')),
  798. // forwarded for with remote IPv6 range trusted
  799. array(array('88.88.88.88'), '2a01:198:603:0:396e:4789:8e99:890f', '88.88.88.88', array('2a01:198:603:0::/65')),
  800. // multiple forwarded for with remote IPv4 addr trusted
  801. array(array('88.88.88.88', '87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89')),
  802. // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted
  803. array(array('87.65.43.21', '127.0.0.1'), '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')),
  804. // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle
  805. array(array('88.88.88.88', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21')),
  806. // multiple forwarded for with remote IPv4 addr and all reverse proxies trusted
  807. array(array('127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21', '88.88.88.88', '127.0.0.1')),
  808. // multiple forwarded for with remote IPv6 addr trusted
  809. array(array('2620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')),
  810. // multiple forwarded for with remote IPv6 addr and some reverse proxies trusted
  811. array(array('3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3')),
  812. // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle
  813. array(array('2620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3,3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3')),
  814. // client IP with port
  815. array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', array('127.0.0.1')),
  816. // invalid forwarded IP is ignored
  817. array(array('88.88.88.88'), '127.0.0.1', 'unknown,88.88.88.88', array('127.0.0.1')),
  818. array(array('88.88.88.88'), '127.0.0.1', '}__test|O:21:&quot;JDatabaseDriverMysqli&quot;:3:{s:2,88.88.88.88', array('127.0.0.1')),
  819. );
  820. }
  821. /**
  822. * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException
  823. * @dataProvider getClientIpsWithConflictingHeadersProvider
  824. */
  825. public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXForwardedFor)
  826. {
  827. $request = new Request();
  828. $server = array(
  829. 'REMOTE_ADDR' => '88.88.88.88',
  830. 'HTTP_FORWARDED' => $httpForwarded,
  831. 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
  832. );
  833. Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED);
  834. $request->initialize(array(), array(), array(), array(), array(), $server);
  835. $request->getClientIps();
  836. }
  837. /**
  838. * @dataProvider getClientIpsWithConflictingHeadersProvider
  839. */
  840. public function testGetClientIpsOnlyXHttpForwardedForTrusted($httpForwarded, $httpXForwardedFor)
  841. {
  842. $request = new Request();
  843. $server = array(
  844. 'REMOTE_ADDR' => '88.88.88.88',
  845. 'HTTP_FORWARDED' => $httpForwarded,
  846. 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
  847. );
  848. Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_FOR);
  849. $request->initialize(array(), array(), array(), array(), array(), $server);
  850. $this->assertSame(array_reverse(explode(',', $httpXForwardedFor)), $request->getClientIps());
  851. }
  852. public function getClientIpsWithConflictingHeadersProvider()
  853. {
  854. // $httpForwarded $httpXForwardedFor
  855. return array(
  856. array('for=87.65.43.21', '192.0.2.60'),
  857. array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60'),
  858. array('for=192.0.2.60', '192.0.2.60,87.65.43.21'),
  859. array('for="::face", for=192.0.2.60', '192.0.2.60,192.0.2.43'),
  860. array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60,87.65.43.21'),
  861. );
  862. }
  863. /**
  864. * @dataProvider getClientIpsWithAgreeingHeadersProvider
  865. */
  866. public function testGetClientIpsWithAgreeingHeaders($httpForwarded, $httpXForwardedFor, $expectedIps)
  867. {
  868. $request = new Request();
  869. $server = array(
  870. 'REMOTE_ADDR' => '88.88.88.88',
  871. 'HTTP_FORWARDED' => $httpForwarded,
  872. 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
  873. );
  874. Request::setTrustedProxies(array('88.88.88.88'), -1);
  875. $request->initialize(array(), array(), array(), array(), array(), $server);
  876. $clientIps = $request->getClientIps();
  877. $this->assertSame($expectedIps, $clientIps);
  878. }
  879. public function getClientIpsWithAgreeingHeadersProvider()
  880. {
  881. // $httpForwarded $httpXForwardedFor
  882. return array(
  883. array('for="192.0.2.60"', '192.0.2.60', array('192.0.2.60')),
  884. array('for=192.0.2.60, for=87.65.43.21', '192.0.2.60,87.65.43.21', array('87.65.43.21', '192.0.2.60')),
  885. array('for="[::face]", for=192.0.2.60', '::face,192.0.2.60', array('192.0.2.60', '::face')),
  886. array('for="192.0.2.60:80"', '192.0.2.60', array('192.0.2.60')),
  887. array('for=192.0.2.60;proto=http;by=203.0.113.43', '192.0.2.60', array('192.0.2.60')),
  888. array('for="[2001:db8:cafe::17]:4711"', '2001:db8:cafe::17', array('2001:db8:cafe::17')),
  889. );
  890. }
  891. public function testGetContentWorksTwiceInDefaultMode()
  892. {
  893. $req = new Request();
  894. $this->assertEquals('', $req->getContent());
  895. $this->assertEquals('', $req->getContent());
  896. }
  897. public function testGetContentReturnsResource()
  898. {
  899. $req = new Request();
  900. $retval = $req->getContent(true);
  901. $this->assertInternalType('resource', $retval);
  902. $this->assertEquals('', fread($retval, 1));
  903. $this->assertTrue(feof($retval));
  904. }
  905. public function testGetContentReturnsResourceWhenContentSetInConstructor()
  906. {
  907. $req = new Request(array(), array(), array(), array(), array(), array(), 'MyContent');
  908. $resource = $req->getContent(true);
  909. $this->assertInternalType('resource', $resource);
  910. $this->assertEquals('MyContent', stream_get_contents($resource));
  911. }
  912. public function testContentAsResource()
  913. {
  914. $resource = fopen('php://memory', 'r+');
  915. fwrite($resource, 'My other content');
  916. rewind($resource);
  917. $req = new Request(array(), array(), array(), array(), array(), array(), $resource);
  918. $this->assertEquals('My other content', stream_get_contents($req->getContent(true)));
  919. $this->assertEquals('My other content', $req->getContent());
  920. }
  921. /**
  922. * @expectedException \LogicException
  923. * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider
  924. */
  925. public function testGetContentCantBeCalledTwiceWithResources($first, $second)
  926. {
  927. if (\PHP_VERSION_ID >= 50600) {
  928. $this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.');
  929. }
  930. $req = new Request();
  931. $req->getContent($first);
  932. $req->getContent($second);
  933. }
  934. public function getContentCantBeCalledTwiceWithResourcesProvider()
  935. {
  936. return array(
  937. 'Resource then fetch' => array(true, false),
  938. 'Resource then resource' => array(true, true),
  939. );
  940. }
  941. /**
  942. * @dataProvider getContentCanBeCalledTwiceWithResourcesProvider
  943. * @requires PHP 5.6
  944. */
  945. public function testGetContentCanBeCalledTwiceWithResources($first, $second)
  946. {
  947. $req = new Request();
  948. $a = $req->getContent($first);
  949. $b = $req->getContent($second);
  950. if ($first) {
  951. $a = stream_get_contents($a);
  952. }
  953. if ($second) {
  954. $b = stream_get_contents($b);
  955. }
  956. $this->assertSame($a, $b);
  957. }
  958. public function getContentCanBeCalledTwiceWithResourcesProvider()
  959. {
  960. return array(
  961. 'Fetch then fetch' => array(false, false),
  962. 'Fetch then resource' => array(false, true),
  963. 'Resource then fetch' => array(true, false),
  964. 'Resource then resource' => array(true, true),
  965. );
  966. }
  967. public function provideOverloadedMethods()
  968. {
  969. return array(
  970. array('PUT'),
  971. array('DELETE'),
  972. array('PATCH'),
  973. array('put'),
  974. array('delete'),
  975. array('patch'),
  976. );
  977. }
  978. /**
  979. * @dataProvider provideOverloadedMethods
  980. */
  981. public function testCreateFromGlobals($method)
  982. {
  983. $normalizedMethod = strtoupper($method);
  984. $_GET['foo1'] = 'bar1';
  985. $_POST['foo2'] = 'bar2';
  986. $_COOKIE['foo3'] = 'bar3';
  987. $_FILES['foo4'] = array('bar4');
  988. $_SERVER['foo5'] = 'bar5';
  989. $request = Request::createFromGlobals();
  990. $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET');
  991. $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST');
  992. $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE');
  993. $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES');
  994. $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER');
  995. unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']);
  996. $_SERVER['REQUEST_METHOD'] = $method;
  997. $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
  998. $request = RequestContentProxy::createFromGlobals();
  999. $this->assertEquals($normalizedMethod, $request->getMethod());
  1000. $this->assertEquals('mycontent', $request->request->get('content'));
  1001. unset($_SERVER['REQUEST_METHOD'], $_SERVER['CONTENT_TYPE']);
  1002. Request::createFromGlobals();
  1003. Request::enableHttpMethodParameterOverride();
  1004. $_POST['_method'] = $method;
  1005. $_POST['foo6'] = 'bar6';
  1006. $_SERVER['REQUEST_METHOD'] = 'PoSt';
  1007. $request = Request::createFromGlobals();
  1008. $this->assertEquals($normalizedMethod, $request->getMethod());
  1009. $this->assertEquals('POST', $request->getRealMethod());
  1010. $this->assertEquals('bar6', $request->request->get('foo6'));
  1011. unset($_POST['_method'], $_POST['foo6'], $_SERVER['REQUEST_METHOD']);
  1012. $this->disableHttpMethodParameterOverride();
  1013. }
  1014. public function testOverrideGlobals()
  1015. {
  1016. $request = new Request();
  1017. $request->initialize(array('foo' => 'bar'));
  1018. // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it
  1019. $server = $_SERVER;
  1020. $request->overrideGlobals();
  1021. $this->assertEquals(array('foo' => 'bar'), $_GET);
  1022. $request->initialize(array(), array('foo' => 'bar'));
  1023. $request->overrideGlobals();
  1024. $this->assertEquals(array('foo' => 'bar'), $_POST);
  1025. $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
  1026. $request->headers->set('X_FORWARDED_PROTO', 'https');
  1027. Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL);
  1028. $this->assertFalse($request->isSecure());
  1029. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  1030. $this->assertTrue($request->isSecure());
  1031. $request->overrideGlobals();
  1032. $this->assertArrayHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER);
  1033. $request->headers->set('CONTENT_TYPE', 'multipart/form-data');
  1034. $request->headers->set('CONTENT_LENGTH', 12345);
  1035. $request->overrideGlobals();
  1036. $this->assertArrayHasKey('CONTENT_TYPE', $_SERVER);
  1037. $this->assertArrayHasKey('CONTENT_LENGTH', $_SERVER);
  1038. $request->initialize(array('foo' => 'bar', 'baz' => 'foo'));
  1039. $request->query->remove('baz');
  1040. $request->overrideGlobals();
  1041. $this->assertEquals(array('foo' => 'bar'), $_GET);
  1042. $this->assertEquals('foo=bar', $_SERVER['QUERY_STRING']);
  1043. $this->assertEquals('foo=bar', $request->server->get('QUERY_STRING'));
  1044. // restore initial $_SERVER array
  1045. $_SERVER = $server;
  1046. }
  1047. public function testGetScriptName()
  1048. {
  1049. $request = new Request();
  1050. $this->assertEquals('', $request->getScriptName());
  1051. $server = array();
  1052. $server['SCRIPT_NAME'] = '/index.php';
  1053. $request->initialize(array(), array(), array(), array(), array(), $server);
  1054. $this->assertEquals('/index.php', $request->getScriptName());
  1055. $server = array();
  1056. $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
  1057. $request->initialize(array(), array(), array(), array(), array(), $server);
  1058. $this->assertEquals('/frontend.php', $request->getScriptName());
  1059. $server = array();
  1060. $server['SCRIPT_NAME'] = '/index.php';
  1061. $server['ORIG_SCRIPT_NAME'] = '/frontend.php';
  1062. $request->initialize(array(), array(), array(), array(), array(), $server);
  1063. $this->assertEquals('/index.php', $request->getScriptName());
  1064. }
  1065. public function testGetBasePath()
  1066. {
  1067. $request = new Request();
  1068. $this->assertEquals('', $request->getBasePath());
  1069. $server = array();
  1070. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  1071. $request->initialize(array(), array(), array(), array(), array(), $server);
  1072. $this->assertEquals('', $request->getBasePath());
  1073. $server = array();
  1074. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  1075. $server['SCRIPT_NAME'] = '/index.php';
  1076. $request->initialize(array(), array(), array(), array(), array(), $server);
  1077. $this->assertEquals('', $request->getBasePath());
  1078. $server = array();
  1079. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  1080. $server['PHP_SELF'] = '/index.php';
  1081. $request->initialize(array(), array(), array(), array(), array(), $server);
  1082. $this->assertEquals('', $request->getBasePath());
  1083. $server = array();
  1084. $server['SCRIPT_FILENAME'] = '/some/where/index.php';
  1085. $server['ORIG_SCRIPT_NAME'] = '/index.php';
  1086. $request->initialize(array(), array(), array(), array(), array(), $server);
  1087. $this->assertEquals('', $request->getBasePath());
  1088. }
  1089. public function testGetPathInfo()
  1090. {
  1091. $request = new Request();
  1092. $this->assertEquals('/', $request->getPathInfo());
  1093. $server = array();
  1094. $server['REQUEST_URI'] = '/path/info';
  1095. $request->initialize(array(), array(), array(), array(), array(), $server);
  1096. $this->assertEquals('/path/info', $request->getPathInfo());
  1097. $server = array();
  1098. $server['REQUEST_URI'] = '/path%20test/info';
  1099. $request->initialize(array(), array(), array(), array(), array(), $server);
  1100. $this->assertEquals('/path%20test/info', $request->getPathInfo());
  1101. $server = array();
  1102. $server['REQUEST_URI'] = '?a=b';
  1103. $request->initialize(array(), array(), array(), array(), array(), $server);
  1104. $this->assertEquals('/', $request->getPathInfo());
  1105. }
  1106. public function testGetParameterPrecedence()
  1107. {
  1108. $request = new Request();
  1109. $request->attributes->set('foo', 'attr');
  1110. $request->query->set('foo', 'query');
  1111. $request->request->set('foo', 'body');
  1112. $this->assertSame('attr', $request->get('foo'));
  1113. $request->attributes->remove('foo');
  1114. $this->assertSame('query', $request->get('foo'));
  1115. $request->query->remove('foo');
  1116. $this->assertSame('body', $request->get('foo'));
  1117. $request->request->remove('foo');
  1118. $this->assertNull($request->get('foo'));
  1119. }
  1120. public function testGetPreferredLanguage()
  1121. {
  1122. $request = new Request();
  1123. $this->assertNull($request->getPreferredLanguage());
  1124. $this->assertNull($request->getPreferredLanguage(array()));
  1125. $this->assertEquals('fr', $request->getPreferredLanguage(array('fr')));
  1126. $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en')));
  1127. $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr')));
  1128. $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr')));
  1129. $request = new Request();
  1130. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  1131. $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us')));
  1132. $request = new Request();
  1133. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  1134. $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
  1135. $request = new Request();
  1136. $request->headers->set('Accept-language', 'zh, en-us; q=0.8');
  1137. $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
  1138. $request = new Request();
  1139. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, fr-fr; q=0.6, fr; q=0.5');
  1140. $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en')));
  1141. }
  1142. public function testIsXmlHttpRequest()
  1143. {
  1144. $request = new Request();
  1145. $this->assertFalse($request->isXmlHttpRequest());
  1146. $request->headers->set('X-Requested-With', 'XMLHttpRequest');
  1147. $this->assertTrue($request->isXmlHttpRequest());
  1148. $request->headers->remove('X-Requested-With');
  1149. $this->assertFalse($request->isXmlHttpRequest());
  1150. }
  1151. /**
  1152. * @requires extension intl
  1153. */
  1154. public function testIntlLocale()
  1155. {
  1156. $request = new Request();
  1157. $request->setDefaultLocale('fr');
  1158. $this->assertEquals('fr', $request->getLocale());
  1159. $this->assertEquals('fr', \Locale::getDefault());
  1160. $request->setLocale('en');
  1161. $this->assertEquals('en', $request->getLocale());
  1162. $this->assertEquals('en', \Locale::getDefault());
  1163. $request->setDefaultLocale('de');
  1164. $this->assertEquals('en', $request->getLocale());
  1165. $this->assertEquals('en', \Locale::getDefault());
  1166. }
  1167. public function testGetCharsets()
  1168. {
  1169. $request = new Request();
  1170. $this->assertEquals(array(), $request->getCharsets());
  1171. $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
  1172. $this->assertEquals(array(), $request->getCharsets()); // testing caching
  1173. $request = new Request();
  1174. $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6');
  1175. $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets());
  1176. $request = new Request();
  1177. $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7');
  1178. $this->assertEquals(array('ISO-8859-1', 'utf-8', '*'), $request->getCharsets());
  1179. }
  1180. public function testGetEncodings()
  1181. {
  1182. $request = new Request();
  1183. $this->assertEquals(array(), $request->getEncodings());
  1184. $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch');
  1185. $this->assertEquals(array(), $request->getEncodings()); // testing caching
  1186. $request = new Request();
  1187. $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch');
  1188. $this->assertEquals(array('gzip', 'deflate', 'sdch'), $request->getEncodings());
  1189. $request = new Request();
  1190. $request->headers->set('Accept-Encoding', 'gzip;q=0.4,deflate;q=0.9,compress;q=0.7');
  1191. $this->assertEquals(array('deflate', 'compress', 'gzip'), $request->getEncodings());
  1192. }
  1193. public function testGetAcceptableContentTypes()
  1194. {
  1195. $request = new Request();
  1196. $this->assertEquals(array(), $request->getAcceptableContentTypes());
  1197. $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
  1198. $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching
  1199. $request = new Request();
  1200. $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*');
  1201. $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());
  1202. }
  1203. public function testGetLanguages()
  1204. {
  1205. $request = new Request();
  1206. $this->assertEquals(array(), $request->getLanguages());
  1207. $request = new Request();
  1208. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  1209. $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());
  1210. $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages());
  1211. $request = new Request();
  1212. $request->headers->set('Accept-language', 'zh, en-us; q=0.6, en; q=0.8');
  1213. $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test out of order qvalues
  1214. $request = new Request();
  1215. $request->headers->set('Accept-language', 'zh, en, en-us');
  1216. $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test equal weighting without qvalues
  1217. $request = new Request();
  1218. $request->headers->set('Accept-language', 'zh; q=0.6, en, en-us; q=0.6');
  1219. $this->assertEquals(array('en', 'zh', 'en_US'), $request->getLanguages()); // Test equal weighting with qvalues
  1220. $request = new Request();
  1221. $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6');
  1222. $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages());
  1223. }
  1224. public function testGetRequestFormat()
  1225. {
  1226. $request = new Request();
  1227. $this->assertEquals('html', $request->getRequestFormat());
  1228. // Ensure that setting different default values over time is possible,
  1229. // aka. setRequestFormat determines the state.
  1230. $this->assertEquals('json', $request->getRequestFormat('json'));
  1231. $this->assertEquals('html', $request->getRequestFormat('html'));
  1232. $request = new Request();
  1233. $this->assertNull($request->getRequestFormat(null));
  1234. $request = new Request();
  1235. $this->assertNull($request->setRequestFormat('foo'));
  1236. $this->assertEquals('foo', $request->getRequestFormat(null));
  1237. $request = new Request(array('_format' => 'foo'));
  1238. $this->assertEquals('html', $request->getRequestFormat());
  1239. }
  1240. public function testHasSession()
  1241. {
  1242. $request = new Request();
  1243. $this->assertFalse($request->hasSession());
  1244. $request->setSession(new Session(new MockArraySessionStorage()));
  1245. $this->assertTrue($request->hasSession());
  1246. }
  1247. public function testGetSession()
  1248. {
  1249. $request = new Request();
  1250. $request->setSession(new Session(new MockArraySessionStorage()));
  1251. $this->assertTrue($request->hasSession());
  1252. $session = $request->getSession();
  1253. $this->assertObjectHasAttribute('storage', $session);
  1254. $this->assertObjectHasAttribute('flashName', $session);
  1255. $this->assertObjectHasAttribute('attributeName', $session);
  1256. }
  1257. public function testHasPreviousSession()
  1258. {
  1259. $request = new Request();
  1260. $this->assertFalse($request->hasPreviousSession());
  1261. $request->cookies->set('MOCKSESSID', 'foo');
  1262. $this->assertFalse($request->hasPreviousSession());
  1263. $request->setSession(new Session(new MockArraySessionStorage()));
  1264. $this->assertTrue($request->hasPreviousSession());
  1265. }
  1266. public function testToString()
  1267. {
  1268. $request = new Request();
  1269. $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6');
  1270. $request->cookies->set('Foo', 'Bar');
  1271. $asString = (string) $request;
  1272. $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString);
  1273. $this->assertContains('Cookie: Foo=Bar', $asString);
  1274. $request->cookies->set('Another', 'Cookie');
  1275. $asString = (string) $request;
  1276. $this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString);
  1277. }
  1278. public function testIsMethod()
  1279. {
  1280. $request = new Request();
  1281. $request->setMethod('POST');
  1282. $this->assertTrue($request->isMethod('POST'));
  1283. $this->assertTrue($request->isMethod('post'));
  1284. $this->assertFalse($request->isMethod('GET'));
  1285. $this->assertFalse($request->isMethod('get'));
  1286. $request->setMethod('GET');
  1287. $this->assertTrue($request->isMethod('GET'));
  1288. $this->assertTrue($request->isMethod('get'));
  1289. $this->assertFalse($request->isMethod('POST'));
  1290. $this->assertFalse($request->isMethod('post'));
  1291. }
  1292. /**
  1293. * @dataProvider getBaseUrlData
  1294. */
  1295. public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo)
  1296. {
  1297. $request = Request::create($uri, 'GET', array(), array(), array(), $server);
  1298. $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl');
  1299. $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo');
  1300. }
  1301. public function getBaseUrlData()
  1302. {
  1303. return array(
  1304. array(
  1305. '/fruit/strawberry/1234index.php/blah',
  1306. array(
  1307. 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/fruit/index.php',
  1308. 'SCRIPT_NAME' => '/fruit/index.php',
  1309. 'PHP_SELF' => '/fruit/index.php',
  1310. ),
  1311. '/fruit',
  1312. '/strawberry/1234index.php/blah',
  1313. ),
  1314. array(
  1315. '/fruit/strawberry/1234index.php/blah',
  1316. array(
  1317. 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/index.php',
  1318. 'SCRIPT_NAME' => '/index.php',
  1319. 'PHP_SELF' => '/index.php',
  1320. ),
  1321. '',
  1322. '/fruit/strawberry/1234index.php/blah',
  1323. ),
  1324. array(
  1325. '/foo%20bar/',
  1326. array(
  1327. 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
  1328. 'SCRIPT_NAME' => '/foo bar/app.php',
  1329. 'PHP_SELF' => '/foo bar/app.php',
  1330. ),
  1331. '/foo%20bar',
  1332. '/',
  1333. ),
  1334. array(
  1335. '/foo%20bar/home',
  1336. array(
  1337. 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
  1338. 'SCRIPT_NAME' => '/foo bar/app.php',
  1339. 'PHP_SELF' => '/foo bar/app.php',
  1340. ),
  1341. '/foo%20bar',
  1342. '/home',
  1343. ),
  1344. array(
  1345. '/foo%20bar/app.php/home',
  1346. array(
  1347. 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
  1348. 'SCRIPT_NAME' => '/foo bar/app.php',
  1349. 'PHP_SELF' => '/foo bar/app.php',
  1350. ),
  1351. '/foo%20bar/app.php',
  1352. '/home',
  1353. ),
  1354. array(
  1355. '/foo%20bar/app.php/home%3Dbaz',
  1356. array(
  1357. 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php',
  1358. 'SCRIPT_NAME' => '/foo bar/app.php',
  1359. 'PHP_SELF' => '/foo bar/app.php',
  1360. ),
  1361. '/foo%20bar/app.php',
  1362. '/home%3Dbaz',
  1363. ),
  1364. array(
  1365. '/foo/bar+baz',
  1366. array(
  1367. 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php',
  1368. 'SCRIPT_NAME' => '/foo/app.php',
  1369. 'PHP_SELF' => '/foo/app.php',
  1370. ),
  1371. '/foo',
  1372. '/bar+baz',
  1373. ),
  1374. );
  1375. }
  1376. /**
  1377. * @dataProvider urlencodedStringPrefixData
  1378. */
  1379. public function testUrlencodedStringPrefix($string, $prefix, $expect)
  1380. {
  1381. $request = new Request();
  1382. $me = new \ReflectionMethod($request, 'getUrlencodedPrefix');
  1383. $me->setAccessible(true);
  1384. $this->assertSame($expect, $me->invoke($request, $string, $prefix));
  1385. }
  1386. public function urlencodedStringPrefixData()
  1387. {
  1388. return array(
  1389. array('foo', 'foo', 'foo'),
  1390. array('fo%6f', 'foo', 'fo%6f'),
  1391. array('foo/bar', 'foo', 'foo'),
  1392. array('fo%6f/bar', 'foo', 'fo%6f'),
  1393. array('f%6f%6f/bar', 'foo', 'f%6f%6f'),
  1394. array('%66%6F%6F/bar', 'foo', '%66%6F%6F'),
  1395. array('fo+o/bar', 'fo+o', 'fo+o'),
  1396. array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'),
  1397. );
  1398. }
  1399. private function disableHttpMethodParameterOverride()
  1400. {
  1401. $class = new \ReflectionClass('Symfony\\Component\\HttpFoundation\\Request');
  1402. $property = $class->getProperty('httpMethodParameterOverride');
  1403. $property->setAccessible(true);
  1404. $property->setValue(false);
  1405. }
  1406. private function getRequestInstanceForClientIpTests($remoteAddr, $httpForwardedFor, $trustedProxies)
  1407. {
  1408. $request = new Request();
  1409. $server = array('REMOTE_ADDR' => $remoteAddr);
  1410. if (null !== $httpForwardedFor) {
  1411. $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor;
  1412. }
  1413. if ($trustedProxies) {
  1414. Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL);
  1415. }
  1416. $request->initialize(array(), array(), array(), array(), array(), $server);
  1417. return $request;
  1418. }
  1419. private function getRequestInstanceForClientIpsForwardedTests($remoteAddr, $httpForwarded, $trustedProxies)
  1420. {
  1421. $request = new Request();
  1422. $server = array('REMOTE_ADDR' => $remoteAddr);
  1423. if (null !== $httpForwarded) {
  1424. $server['HTTP_FORWARDED'] = $httpForwarded;
  1425. }
  1426. if ($trustedProxies) {
  1427. Request::setTrustedProxies($trustedProxies, Request::HEADER_FORWARDED);
  1428. }
  1429. $request->initialize(array(), array(), array(), array(), array(), $server);
  1430. return $request;
  1431. }
  1432. public function testTrustedProxiesXForwardedFor()
  1433. {
  1434. $request = Request::create('http://example.com/');
  1435. $request->server->set('REMOTE_ADDR', '3.3.3.3');
  1436. $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2');
  1437. $request->headers->set('X_FORWARDED_HOST', 'foo.example.com:1234, real.example.com:8080');
  1438. $request->headers->set('X_FORWARDED_PROTO', 'https');
  1439. $request->headers->set('X_FORWARDED_PORT', 443);
  1440. // no trusted proxies
  1441. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1442. $this->assertEquals('example.com', $request->getHost());
  1443. $this->assertEquals(80, $request->getPort());
  1444. $this->assertFalse($request->isSecure());
  1445. // disabling proxy trusting
  1446. Request::setTrustedProxies(array(), Request::HEADER_X_FORWARDED_ALL);
  1447. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1448. $this->assertEquals('example.com', $request->getHost());
  1449. $this->assertEquals(80, $request->getPort());
  1450. $this->assertFalse($request->isSecure());
  1451. // request is forwarded by a non-trusted proxy
  1452. Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
  1453. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1454. $this->assertEquals('example.com', $request->getHost());
  1455. $this->assertEquals(80, $request->getPort());
  1456. $this->assertFalse($request->isSecure());
  1457. // trusted proxy via setTrustedProxies()
  1458. Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
  1459. $this->assertEquals('1.1.1.1', $request->getClientIp());
  1460. $this->assertEquals('foo.example.com', $request->getHost());
  1461. $this->assertEquals(443, $request->getPort());
  1462. $this->assertTrue($request->isSecure());
  1463. // trusted proxy via setTrustedProxies()
  1464. Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
  1465. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1466. $this->assertEquals('example.com', $request->getHost());
  1467. $this->assertEquals(80, $request->getPort());
  1468. $this->assertFalse($request->isSecure());
  1469. // check various X_FORWARDED_PROTO header values
  1470. Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
  1471. $request->headers->set('X_FORWARDED_PROTO', 'ssl');
  1472. $this->assertTrue($request->isSecure());
  1473. $request->headers->set('X_FORWARDED_PROTO', 'https, http');
  1474. $this->assertTrue($request->isSecure());
  1475. }
  1476. /**
  1477. * @group legacy
  1478. * @expectedDeprecation The "Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.
  1479. */
  1480. public function testLegacyTrustedProxies()
  1481. {
  1482. $request = Request::create('http://example.com/');
  1483. $request->server->set('REMOTE_ADDR', '3.3.3.3');
  1484. $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2');
  1485. $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080');
  1486. $request->headers->set('X_FORWARDED_PROTO', 'https');
  1487. $request->headers->set('X_FORWARDED_PORT', 443);
  1488. $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4');
  1489. $request->headers->set('X_MY_HOST', 'my.example.com');
  1490. $request->headers->set('X_MY_PROTO', 'http');
  1491. $request->headers->set('X_MY_PORT', 81);
  1492. Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL);
  1493. // custom header names
  1494. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR');
  1495. Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST');
  1496. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT');
  1497. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO');
  1498. $this->assertEquals('4.4.4.4', $request->getClientIp());
  1499. $this->assertEquals('my.example.com', $request->getHost());
  1500. $this->assertEquals(81, $request->getPort());
  1501. $this->assertFalse($request->isSecure());
  1502. // disabling via empty header names
  1503. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null);
  1504. Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null);
  1505. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null);
  1506. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null);
  1507. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1508. $this->assertEquals('example.com', $request->getHost());
  1509. $this->assertEquals(80, $request->getPort());
  1510. $this->assertFalse($request->isSecure());
  1511. //reset
  1512. Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED');
  1513. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR');
  1514. Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST');
  1515. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT');
  1516. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO');
  1517. }
  1518. public function testTrustedProxiesForwarded()
  1519. {
  1520. $request = Request::create('http://example.com/');
  1521. $request->server->set('REMOTE_ADDR', '3.3.3.3');
  1522. $request->headers->set('FORWARDED', 'for=1.1.1.1, host=foo.example.com:8080, proto=https, for=2.2.2.2, host=real.example.com:8080');
  1523. // no trusted proxies
  1524. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1525. $this->assertEquals('example.com', $request->getHost());
  1526. $this->assertEquals(80, $request->getPort());
  1527. $this->assertFalse($request->isSecure());
  1528. // disabling proxy trusting
  1529. Request::setTrustedProxies(array(), Request::HEADER_FORWARDED);
  1530. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1531. $this->assertEquals('example.com', $request->getHost());
  1532. $this->assertEquals(80, $request->getPort());
  1533. $this->assertFalse($request->isSecure());
  1534. // request is forwarded by a non-trusted proxy
  1535. Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_FORWARDED);
  1536. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1537. $this->assertEquals('example.com', $request->getHost());
  1538. $this->assertEquals(80, $request->getPort());
  1539. $this->assertFalse($request->isSecure());
  1540. // trusted proxy via setTrustedProxies()
  1541. Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED);
  1542. $this->assertEquals('1.1.1.1', $request->getClientIp());
  1543. $this->assertEquals('foo.example.com', $request->getHost());
  1544. $this->assertEquals(8080, $request->getPort());
  1545. $this->assertTrue($request->isSecure());
  1546. // trusted proxy via setTrustedProxies()
  1547. Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_FORWARDED);
  1548. $this->assertEquals('3.3.3.3', $request->getClientIp());
  1549. $this->assertEquals('example.com', $request->getHost());
  1550. $this->assertEquals(80, $request->getPort());
  1551. $this->assertFalse($request->isSecure());
  1552. // check various X_FORWARDED_PROTO header values
  1553. Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED);
  1554. $request->headers->set('FORWARDED', 'proto=ssl');
  1555. $this->assertTrue($request->isSecure());
  1556. $request->headers->set('FORWARDED', 'proto=https, proto=http');
  1557. $this->assertTrue($request->isSecure());
  1558. }
  1559. /**
  1560. * @group legacy
  1561. * @expectedException \InvalidArgumentException
  1562. */
  1563. public function testSetTrustedProxiesInvalidHeaderName()
  1564. {
  1565. Request::create('http://example.com/');
  1566. Request::setTrustedHeaderName('bogus name', 'X_MY_FOR');
  1567. }
  1568. /**
  1569. * @group legacy
  1570. * @expectedException \InvalidArgumentException
  1571. */
  1572. public function testGetTrustedProxiesInvalidHeaderName()
  1573. {
  1574. Request::create('http://example.com/');
  1575. Request::getTrustedHeaderName('bogus name');
  1576. }
  1577. /**
  1578. * @dataProvider iisRequestUriProvider
  1579. */
  1580. public function testIISRequestUri($headers, $server, $expectedRequestUri)
  1581. {
  1582. $request = new Request();
  1583. $request->headers->replace($headers);
  1584. $request->server->replace($server);
  1585. $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct');
  1586. $subRequestUri = '/bar/foo';
  1587. $subRequest = Request::create($subRequestUri, 'get', array(), array(), array(), $request->server->all());
  1588. $this->assertEquals($subRequestUri, $subRequest->getRequestUri(), '->getRequestUri() is correct in sub request');
  1589. }
  1590. public function iisRequestUriProvider()
  1591. {
  1592. return array(
  1593. array(
  1594. array(),
  1595. array(
  1596. 'IIS_WasUrlRewritten' => '1',
  1597. 'UNENCODED_URL' => '/foo/bar',
  1598. ),
  1599. '/foo/bar',
  1600. ),
  1601. array(
  1602. array(),
  1603. array(
  1604. 'ORIG_PATH_INFO' => '/foo/bar',
  1605. ),
  1606. '/foo/bar',
  1607. ),
  1608. array(
  1609. array(),
  1610. array(
  1611. 'ORIG_PATH_INFO' => '/foo/bar',
  1612. 'QUERY_STRING' => 'foo=bar',
  1613. ),
  1614. '/foo/bar?foo=bar',
  1615. ),
  1616. );
  1617. }
  1618. public function testTrustedHosts()
  1619. {
  1620. // create a request
  1621. $request = Request::create('/');
  1622. // no trusted host set -> no host check
  1623. $request->headers->set('host', 'evil.com');
  1624. $this->assertEquals('evil.com', $request->getHost());
  1625. // add a trusted domain and all its subdomains
  1626. Request::setTrustedHosts(array('^([a-z]{9}\.)?trusted\.com$'));
  1627. // untrusted host
  1628. $request->headers->set('host', 'evil.com');
  1629. try {
  1630. $request->getHost();
  1631. $this->fail('Request::getHost() should throw an exception when host is not trusted.');
  1632. } catch (SuspiciousOperationException $e) {
  1633. $this->assertEquals('Untrusted Host "evil.com".', $e->getMessage());
  1634. }
  1635. // trusted hosts
  1636. $request->headers->set('host', 'trusted.com');
  1637. $this->assertEquals('trusted.com', $request->getHost());
  1638. $this->assertEquals(80, $request->getPort());
  1639. $request->server->set('HTTPS', true);
  1640. $request->headers->set('host', 'trusted.com');
  1641. $this->assertEquals('trusted.com', $request->getHost());
  1642. $this->assertEquals(443, $request->getPort());
  1643. $request->server->set('HTTPS', false);
  1644. $request->headers->set('host', 'trusted.com:8000');
  1645. $this->assertEquals('trusted.com', $request->getHost());
  1646. $this->assertEquals(8000, $request->getPort());
  1647. $request->headers->set('host', 'subdomain.trusted.com');
  1648. $this->assertEquals('subdomain.trusted.com', $request->getHost());
  1649. }
  1650. public function testSetTrustedHostsDoesNotBreakOnSpecialCharacters()
  1651. {
  1652. Request::setTrustedHosts(array('localhost(\.local){0,1}#,example.com', 'localhost'));
  1653. $request = Request::create('/');
  1654. $request->headers->set('host', 'localhost');
  1655. $this->assertSame('localhost', $request->getHost());
  1656. }
  1657. public function testFactory()
  1658. {
  1659. Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) {
  1660. return new NewRequest();
  1661. });
  1662. $this->assertEquals('foo', Request::create('/')->getFoo());
  1663. Request::setFactory(null);
  1664. }
  1665. /**
  1666. * @dataProvider getLongHostNames
  1667. */
  1668. public function testVeryLongHosts($host)
  1669. {
  1670. $start = microtime(true);
  1671. $request = Request::create('/');
  1672. $request->headers->set('host', $host);
  1673. $this->assertEquals($host, $request->getHost());
  1674. $this->assertLessThan(5, microtime(true) - $start);
  1675. }
  1676. /**
  1677. * @dataProvider getHostValidities
  1678. */
  1679. public function testHostValidity($host, $isValid, $expectedHost = null, $expectedPort = null)
  1680. {
  1681. $request = Request::create('/');
  1682. $request->headers->set('host', $host);
  1683. if ($isValid) {
  1684. $this->assertSame($expectedHost ?: $host, $request->getHost());
  1685. if ($expectedPort) {
  1686. $this->assertSame($expectedPort, $request->getPort());
  1687. }
  1688. } else {
  1689. if (method_exists($this, 'expectException')) {
  1690. $this->expectException(SuspiciousOperationException::class);
  1691. $this->expectExceptionMessage('Invalid Host');
  1692. } else {
  1693. $this->setExpectedException(SuspiciousOperationException::class, 'Invalid Host');
  1694. }
  1695. $request->getHost();
  1696. }
  1697. }
  1698. public function getHostValidities()
  1699. {
  1700. return array(
  1701. array('.a', false),
  1702. array('a..', false),
  1703. array('a.', true),
  1704. array("\xE9", false),
  1705. array('[::1]', true),
  1706. array('[::1]:80', true, '[::1]', 80),
  1707. array(str_repeat('.', 101), false),
  1708. );
  1709. }
  1710. public function getLongHostNames()
  1711. {
  1712. return array(
  1713. array('a'.str_repeat('.a', 40000)),
  1714. array(str_repeat(':', 101)),
  1715. );
  1716. }
  1717. /**
  1718. * @dataProvider methodIdempotentProvider
  1719. */
  1720. public function testMethodIdempotent($method, $idempotent)
  1721. {
  1722. $request = new Request();
  1723. $request->setMethod($method);
  1724. $this->assertEquals($idempotent, $request->isMethodIdempotent());
  1725. }
  1726. public function methodIdempotentProvider()
  1727. {
  1728. return array(
  1729. array('HEAD', true),
  1730. array('GET', true),
  1731. array('POST', false),
  1732. array('PUT', true),
  1733. array('PATCH', false),
  1734. array('DELETE', true),
  1735. array('PURGE', true),
  1736. array('OPTIONS', true),
  1737. array('TRACE', true),
  1738. array('CONNECT', false),
  1739. );
  1740. }
  1741. /**
  1742. * @dataProvider methodSafeProvider
  1743. */
  1744. public function testMethodSafe($method, $safe)
  1745. {
  1746. $request = new Request();
  1747. $request->setMethod($method);
  1748. $this->assertEquals($safe, $request->isMethodSafe(false));
  1749. }
  1750. public function methodSafeProvider()
  1751. {
  1752. return array(
  1753. array('HEAD', true),
  1754. array('GET', true),
  1755. array('POST', false),
  1756. array('PUT', false),
  1757. array('PATCH', false),
  1758. array('DELETE', false),
  1759. array('PURGE', false),
  1760. array('OPTIONS', true),
  1761. array('TRACE', true),
  1762. array('CONNECT', false),
  1763. );
  1764. }
  1765. /**
  1766. * @group legacy
  1767. * @expectedDeprecation Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since Symfony 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead.
  1768. */
  1769. public function testMethodSafeChecksCacheable()
  1770. {
  1771. $request = new Request();
  1772. $request->setMethod('OPTIONS');
  1773. $this->assertFalse($request->isMethodSafe());
  1774. }
  1775. /**
  1776. * @dataProvider methodCacheableProvider
  1777. */
  1778. public function testMethodCacheable($method, $cacheable)
  1779. {
  1780. $request = new Request();
  1781. $request->setMethod($method);
  1782. $this->assertEquals($cacheable, $request->isMethodCacheable());
  1783. }
  1784. public function methodCacheableProvider()
  1785. {
  1786. return array(
  1787. array('HEAD', true),
  1788. array('GET', true),
  1789. array('POST', false),
  1790. array('PUT', false),
  1791. array('PATCH', false),
  1792. array('DELETE', false),
  1793. array('PURGE', false),
  1794. array('OPTIONS', false),
  1795. array('TRACE', false),
  1796. array('CONNECT', false),
  1797. );
  1798. }
  1799. /**
  1800. * @group legacy
  1801. */
  1802. public function testGetTrustedHeaderName()
  1803. {
  1804. Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL);
  1805. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
  1806. $this->assertSame('X_FORWARDED_FOR', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
  1807. $this->assertSame('X_FORWARDED_HOST', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
  1808. $this->assertSame('X_FORWARDED_PORT', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
  1809. $this->assertSame('X_FORWARDED_PROTO', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
  1810. Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
  1811. $this->assertSame('FORWARDED', Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
  1812. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
  1813. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
  1814. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
  1815. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
  1816. Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'A');
  1817. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'B');
  1818. Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'C');
  1819. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'D');
  1820. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'E');
  1821. Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
  1822. $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
  1823. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
  1824. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
  1825. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
  1826. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
  1827. Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL);
  1828. $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
  1829. $this->assertSame('B', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP));
  1830. $this->assertSame('C', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST));
  1831. $this->assertSame('D', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT));
  1832. $this->assertSame('E', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO));
  1833. Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED);
  1834. $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED));
  1835. //reset
  1836. Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED');
  1837. Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR');
  1838. Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST');
  1839. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT');
  1840. Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO');
  1841. }
  1842. /**
  1843. * @dataProvider protocolVersionProvider
  1844. */
  1845. public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected)
  1846. {
  1847. if ($trustedProxy) {
  1848. Request::setTrustedProxies(array('1.1.1.1'), -1);
  1849. }
  1850. $request = new Request();
  1851. $request->server->set('SERVER_PROTOCOL', $serverProtocol);
  1852. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  1853. $request->headers->set('Via', $via);
  1854. $this->assertSame($expected, $request->getProtocolVersion());
  1855. }
  1856. public function protocolVersionProvider()
  1857. {
  1858. return array(
  1859. 'untrusted without via' => array('HTTP/2.0', false, '', 'HTTP/2.0'),
  1860. 'untrusted with via' => array('HTTP/2.0', false, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/2.0'),
  1861. 'trusted without via' => array('HTTP/2.0', true, '', 'HTTP/2.0'),
  1862. 'trusted with via' => array('HTTP/2.0', true, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'),
  1863. 'trusted with via and protocol name' => array('HTTP/2.0', true, 'HTTP/1.0 fred, HTTP/1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'),
  1864. 'trusted with broken via' => array('HTTP/2.0', true, 'HTTP/1^0 foo', 'HTTP/2.0'),
  1865. 'trusted with partially-broken via' => array('HTTP/2.0', true, '1.0 fred, foo', 'HTTP/1.0'),
  1866. );
  1867. }
  1868. public function nonstandardRequestsData()
  1869. {
  1870. return array(
  1871. array('', '', '/', 'http://host:8080/', ''),
  1872. array('/', '', '/', 'http://host:8080/', ''),
  1873. array('hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),
  1874. array('/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),
  1875. array('', 'a=b', '/', 'http://host:8080/?a=b'),
  1876. array('?a=b', 'a=b', '/', 'http://host:8080/?a=b'),
  1877. array('/?a=b', 'a=b', '/', 'http://host:8080/?a=b'),
  1878. array('x', 'a=b', '/x', 'http://host:8080/x?a=b'),
  1879. array('x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),
  1880. array('/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),
  1881. array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
  1882. array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
  1883. array('hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
  1884. array('hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
  1885. array('/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
  1886. );
  1887. }
  1888. /**
  1889. * @dataProvider nonstandardRequestsData
  1890. */
  1891. public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null)
  1892. {
  1893. if (null === $expectedBaseUrl) {
  1894. $expectedBaseUrl = $expectedBasePath;
  1895. }
  1896. $server = array(
  1897. 'HTTP_HOST' => 'host:8080',
  1898. 'SERVER_PORT' => '8080',
  1899. 'QUERY_STRING' => $queryString,
  1900. 'PHP_SELF' => '/hello/app.php',
  1901. 'SCRIPT_FILENAME' => '/some/path/app.php',
  1902. 'REQUEST_URI' => $requestUri,
  1903. );
  1904. $request = new Request(array(), array(), array(), array(), array(), $server);
  1905. $this->assertEquals($expectedPathInfo, $request->getPathInfo());
  1906. $this->assertEquals($expectedUri, $request->getUri());
  1907. $this->assertEquals($queryString, $request->getQueryString());
  1908. $this->assertEquals(8080, $request->getPort());
  1909. $this->assertEquals('host:8080', $request->getHttpHost());
  1910. $this->assertEquals($expectedBaseUrl, $request->getBaseUrl());
  1911. $this->assertEquals($expectedBasePath, $request->getBasePath());
  1912. }
  1913. public function testTrustedHost()
  1914. {
  1915. Request::setTrustedProxies(array('1.1.1.1'), -1);
  1916. $request = Request::create('/');
  1917. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  1918. $request->headers->set('Forwarded', 'host=localhost:8080');
  1919. $request->headers->set('X-Forwarded-Host', 'localhost:8080');
  1920. $this->assertSame('localhost:8080', $request->getHttpHost());
  1921. $this->assertSame(8080, $request->getPort());
  1922. $request = Request::create('/');
  1923. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  1924. $request->headers->set('Forwarded', 'host="[::1]:443"');
  1925. $request->headers->set('X-Forwarded-Host', '[::1]:443');
  1926. $request->headers->set('X-Forwarded-Port', 443);
  1927. $this->assertSame('[::1]:443', $request->getHttpHost());
  1928. $this->assertSame(443, $request->getPort());
  1929. }
  1930. public function testTrustedPort()
  1931. {
  1932. Request::setTrustedProxies(array('1.1.1.1'), -1);
  1933. $request = Request::create('/');
  1934. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  1935. $request->headers->set('Forwarded', 'host=localhost:8080');
  1936. $request->headers->set('X-Forwarded-Port', 8080);
  1937. $this->assertSame(8080, $request->getPort());
  1938. $request = Request::create('/');
  1939. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  1940. $request->headers->set('Forwarded', 'host=localhost');
  1941. $request->headers->set('X-Forwarded-Port', 80);
  1942. $this->assertSame(80, $request->getPort());
  1943. $request = Request::create('/');
  1944. $request->server->set('REMOTE_ADDR', '1.1.1.1');
  1945. $request->headers->set('Forwarded', 'host="[::1]"');
  1946. $request->headers->set('X-Forwarded-Proto', 'https');
  1947. $request->headers->set('X-Forwarded-Port', 443);
  1948. $this->assertSame(443, $request->getPort());
  1949. }
  1950. }
  1951. class RequestContentProxy extends Request
  1952. {
  1953. public function getContent($asResource = false)
  1954. {
  1955. return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent'), '', '&');
  1956. }
  1957. }
  1958. class NewRequest extends Request
  1959. {
  1960. public function getFoo()
  1961. {
  1962. return 'foo';
  1963. }
  1964. }