vendor/symfony/http-kernel/EventListener/FragmentListener.php line 53

Open in your IDE?
  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\EventListener;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpKernel\Event\RequestEvent;
  14. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  15. use Symfony\Component\HttpKernel\KernelEvents;
  16. use Symfony\Component\HttpKernel\UriSigner;
  17. /**
  18. * Handles content fragments represented by special URIs.
  19. *
  20. * All URL paths starting with /_fragment are handled as
  21. * content fragments by this listener.
  22. *
  23. * Throws an AccessDeniedHttpException exception if the request
  24. * is not signed or if it is not an internal sub-request.
  25. *
  26. * @author Fabien Potencier <fabien@symfony.com>
  27. *
  28. * @final
  29. */
  30. class FragmentListener implements EventSubscriberInterface
  31. {
  32. private $signer;
  33. private $fragmentPath;
  34. /**
  35. * @param string $fragmentPath The path that triggers this listener
  36. */
  37. public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment')
  38. {
  39. $this->signer = $signer;
  40. $this->fragmentPath = $fragmentPath;
  41. }
  42. /**
  43. * Fixes request attributes when the path is '/_fragment'.
  44. *
  45. * @throws AccessDeniedHttpException if the request does not come from a trusted IP
  46. */
  47. public function onKernelRequest(RequestEvent $event)
  48. {
  49. $request = $event->getRequest();
  50. if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) {
  51. return;
  52. }
  53. if ($request->attributes->has('_controller')) {
  54. // Is a sub-request: no need to parse _path but it should still be removed from query parameters as below.
  55. $request->query->remove('_path');
  56. return;
  57. }
  58. if ($event->isMainRequest()) {
  59. $this->validateRequest($request);
  60. }
  61. parse_str($request->query->get('_path', ''), $attributes);
  62. $request->attributes->add($attributes);
  63. $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes));
  64. $request->query->remove('_path');
  65. }
  66. protected function validateRequest(Request $request)
  67. {
  68. // is the Request safe?
  69. if (!$request->isMethodSafe()) {
  70. throw new AccessDeniedHttpException();
  71. }
  72. // is the Request signed?
  73. if ($this->signer->checkRequest($request)) {
  74. return;
  75. }
  76. throw new AccessDeniedHttpException();
  77. }
  78. public static function getSubscribedEvents(): array
  79. {
  80. return [
  81. KernelEvents::REQUEST => [['onKernelRequest', 48]],
  82. ];
  83. }
  84. }