SubRequestHandlerTest.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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\HttpKernel\Tests\HttpCache;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler;
  15. use Symfony\Component\HttpKernel\HttpKernelInterface;
  16. class SubRequestHandlerTest extends TestCase
  17. {
  18. private static $globalState;
  19. protected function setUp(): void
  20. {
  21. self::$globalState = $this->getGlobalState();
  22. }
  23. protected function tearDown(): void
  24. {
  25. Request::setTrustedProxies(self::$globalState[0], self::$globalState[1]);
  26. }
  27. public function testTrustedHeadersAreKept()
  28. {
  29. Request::setTrustedProxies(['10.0.0.1'], -1);
  30. $globalState = $this->getGlobalState();
  31. $request = Request::create('/');
  32. $request->server->set('REMOTE_ADDR', '10.0.0.1');
  33. $request->headers->set('X-Forwarded-For', '10.0.0.2');
  34. $request->headers->set('X-Forwarded-Host', 'Good');
  35. $request->headers->set('X-Forwarded-Port', '1234');
  36. $request->headers->set('X-Forwarded-Proto', 'https');
  37. $request->headers->set('X-Forwarded-Prefix', '/admin');
  38. $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) {
  39. $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR'));
  40. $this->assertSame('10.0.0.2', $request->getClientIp());
  41. $this->assertSame('Good', $request->headers->get('X-Forwarded-Host'));
  42. $this->assertSame('1234', $request->headers->get('X-Forwarded-Port'));
  43. $this->assertSame('https', $request->headers->get('X-Forwarded-Proto'));
  44. $this->assertSame('/admin', $request->headers->get('X-Forwarded-Prefix'));
  45. });
  46. SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MAIN_REQUEST, true);
  47. $this->assertSame($globalState, $this->getGlobalState());
  48. }
  49. public function testUntrustedHeadersAreRemoved()
  50. {
  51. $request = Request::create('/');
  52. $request->server->set('REMOTE_ADDR', '10.0.0.1');
  53. $request->headers->set('X-Forwarded-For', '10.0.0.2');
  54. $request->headers->set('X-Forwarded-Host', 'Evil');
  55. $request->headers->set('X-Forwarded-Port', '1234');
  56. $request->headers->set('X-Forwarded-Proto', 'http');
  57. $request->headers->set('X-Forwarded-Prefix', '/admin');
  58. $request->headers->set('Forwarded', 'Evil2');
  59. $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) {
  60. $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR'));
  61. $this->assertSame('10.0.0.1', $request->getClientIp());
  62. $this->assertFalse($request->headers->has('X-Forwarded-Host'));
  63. $this->assertFalse($request->headers->has('X-Forwarded-Port'));
  64. $this->assertFalse($request->headers->has('X-Forwarded-Proto'));
  65. $this->assertFalse($request->headers->has('X-Forwarded-Prefix'));
  66. $this->assertSame('for="10.0.0.1";host="localhost";proto=http', $request->headers->get('Forwarded'));
  67. });
  68. SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MAIN_REQUEST, true);
  69. $this->assertSame(self::$globalState, $this->getGlobalState());
  70. }
  71. public function testTrustedForwardedHeader()
  72. {
  73. Request::setTrustedProxies(['10.0.0.1'], -1);
  74. $globalState = $this->getGlobalState();
  75. $request = Request::create('/');
  76. $request->server->set('REMOTE_ADDR', '10.0.0.1');
  77. $request->headers->set('Forwarded', 'for="10.0.0.2";host="foo.bar:1234";proto=https');
  78. $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) {
  79. $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR'));
  80. $this->assertSame('10.0.0.2', $request->getClientIp());
  81. $this->assertSame('foo.bar:1234', $request->getHttpHost());
  82. $this->assertSame('https', $request->getScheme());
  83. $this->assertSame(1234, $request->getPort());
  84. });
  85. SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MAIN_REQUEST, true);
  86. $this->assertSame($globalState, $this->getGlobalState());
  87. }
  88. public function testTrustedXForwardedForHeader()
  89. {
  90. Request::setTrustedProxies(['10.0.0.1'], -1);
  91. $globalState = $this->getGlobalState();
  92. $request = Request::create('/');
  93. $request->server->set('REMOTE_ADDR', '10.0.0.1');
  94. $request->headers->set('X-Forwarded-For', '10.0.0.2');
  95. $request->headers->set('X-Forwarded-Host', 'foo.bar');
  96. $request->headers->set('X-Forwarded-Proto', 'https');
  97. $request->headers->set('X-Forwarded-Prefix', '/admin');
  98. $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) {
  99. $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR'));
  100. $this->assertSame('10.0.0.2', $request->getClientIp());
  101. $this->assertSame('foo.bar', $request->getHttpHost());
  102. $this->assertSame('https', $request->getScheme());
  103. $this->assertSame('/admin', $request->getBaseUrl());
  104. });
  105. SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MAIN_REQUEST, true);
  106. $this->assertSame($globalState, $this->getGlobalState());
  107. }
  108. private function getGlobalState()
  109. {
  110. return [
  111. Request::getTrustedProxies(),
  112. Request::getTrustedHeaderSet(),
  113. ];
  114. }
  115. }
  116. class TestSubRequestHandlerKernel implements HttpKernelInterface
  117. {
  118. private $assertCallback;
  119. public function __construct(\Closure $assertCallback)
  120. {
  121. $this->assertCallback = $assertCallback;
  122. }
  123. public function handle(Request $request, $type = self::MAIN_REQUEST, $catch = true): Response
  124. {
  125. $assertCallback = $this->assertCallback;
  126. $assertCallback($request, $type, $catch);
  127. return new Response();
  128. }
  129. }