Пример #1
0
 /**
  * Sets a BigPipe no-JS cookie, redirects back to the original location.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request.
  *
  * @return \Drupal\Core\Routing\LocalRedirectResponse
  *   A response that sets the no-JS cookie and redirects back to the original
  *   location.
  *
  * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
  *   Thrown when the no-JS cookie is already set or when there is no session.
  * @throws \Symfony\Component\HttpKernel\Exception\HttpException
  *   Thrown when the original location is missing, i.e. when no 'destination'
  *   query argument is set.
  *
  * @see \Drupal\big_pipe\Render\Placeholder\BigPipeStrategy
  */
 public function setNoJsCookie(Request $request)
 {
     // This controller may only be accessed when the browser does not support
     // JavaScript. It is accessed automatically when that's the case thanks to
     // big_pipe_page_attachments(). When this controller is executed, deny
     // access when either:
     // - the no-JS cookie is already set: this indicates a redirect loop, since
     //   the cookie was already set, yet the user is executing this controller;
     // - there is no session, in which case BigPipe is not enabled anyway, so it
     //   is pointless to set this cookie.
     if ($request->cookies->has(BigPipeStrategy::NOJS_COOKIE) || $request->getSession() === NULL) {
         throw new AccessDeniedHttpException();
     }
     if (!$request->query->has('destination')) {
         throw new HttpException(500, 'The original location is missing.');
     }
     $response = new LocalRedirectResponse($request->query->get('destination'));
     $response->headers->setCookie(new Cookie(BigPipeStrategy::NOJS_COOKIE, TRUE));
     $response->addCacheableDependency((new CacheableMetadata())->addCacheContexts(['cookies:' . BigPipeStrategy::NOJS_COOKIE, 'session.exists']));
     return $response;
 }
Пример #2
0
 /**
  * Allows manipulation of the response object when performing a redirect.
  *
  * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
  *   The Event to process.
  */
 public function checkRedirectUrl(FilterResponseEvent $event)
 {
     $response = $event->getResponse();
     if ($response instanceof RedirectResponse) {
         $request = $event->getRequest();
         // Let the 'destination' query parameter override the redirect target.
         // If $response is already a SecuredRedirectResponse, it might reject the
         // new target as invalid, in which case proceed with the old target.
         $destination = $request->query->get('destination');
         if ($destination) {
             // The 'Location' HTTP header must always be absolute.
             $destination = $this->getDestinationAsAbsoluteUrl($destination, $request->getSchemeAndHttpHost());
             try {
                 $response->setTargetUrl($destination);
             } catch (\InvalidArgumentException $e) {
             }
         }
         // Regardless of whether the target is the original one or the overridden
         // destination, ensure that all redirects are safe.
         if (!$response instanceof SecuredRedirectResponse) {
             try {
                 // SecuredRedirectResponse is an abstract class that requires a
                 // concrete implementation. Default to LocalRedirectResponse, which
                 // considers only redirects to within the same site as safe.
                 $safe_response = LocalRedirectResponse::createFromRedirectResponse($response);
                 $safe_response->setRequestContext($this->requestContext);
             } catch (\InvalidArgumentException $e) {
                 // If the above failed, it's because the redirect target wasn't
                 // local. Do not follow that redirect. Display an error message
                 // instead. We're already catching one exception, so trigger_error()
                 // rather than throw another one.
                 // We don't throw an exception, because this is a client error rather than a
                 // server error.
                 $message = 'Redirects to external URLs are not allowed by default, use \\Drupal\\Core\\Routing\\TrustedRedirectResponse for it.';
                 trigger_error($message, E_USER_ERROR);
                 $safe_response = new Response($message, 400);
             }
             $event->setResponse($safe_response);
         }
     }
 }