3 namespace Drupal\big_pipe\Controller;
5 use Drupal\big_pipe\Render\Placeholder\BigPipeStrategy;
6 use Drupal\Core\Cache\CacheableMetadata;
7 use Drupal\Core\Routing\LocalRedirectResponse;
8 use Symfony\Component\HttpFoundation\Cookie;
9 use Symfony\Component\HttpFoundation\Request;
10 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
11 use Symfony\Component\HttpKernel\Exception\HttpException;
14 * Returns responses for BigPipe module routes.
16 class BigPipeController {
19 * Sets a BigPipe no-JS cookie, redirects back to the original location.
21 * @param \Symfony\Component\HttpFoundation\Request $request
22 * The current request.
24 * @return \Drupal\Core\Routing\LocalRedirectResponse
25 * A response that sets the no-JS cookie and redirects back to the original
28 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
29 * Thrown when the no-JS cookie is already set or when there is no session.
30 * @throws \Symfony\Component\HttpKernel\Exception\HttpException
31 * Thrown when the original location is missing, i.e. when no 'destination'
32 * query argument is set.
34 * @see \Drupal\big_pipe\Render\Placeholder\BigPipeStrategy
36 public function setNoJsCookie(Request $request) {
37 // This controller may only be accessed when the browser does not support
38 // JavaScript. It is accessed automatically when that's the case thanks to
39 // big_pipe_page_attachments(). When this controller is executed, deny
40 // access when either:
41 // - the no-JS cookie is already set: this indicates a redirect loop, since
42 // the cookie was already set, yet the user is executing this controller;
43 // - there is no session, in which case BigPipe is not enabled anyway, so it
44 // is pointless to set this cookie.
45 if ($request->cookies->has(BigPipeStrategy::NOJS_COOKIE) || $request->getSession() === NULL) {
46 throw new AccessDeniedHttpException();
49 if (!$request->query->has('destination')) {
50 throw new HttpException(400, 'The original location is missing.');
53 $response = new LocalRedirectResponse($request->query->get('destination'));
54 // Set cookie without httpOnly, so that JavaScript can delete it.
55 $response->headers->setCookie(new Cookie(BigPipeStrategy::NOJS_COOKIE, TRUE, 0, '/', NULL, FALSE, FALSE));
56 $response->addCacheableDependency((new CacheableMetadata())->addCacheContexts(['cookies:' . BigPipeStrategy::NOJS_COOKIE, 'session.exists']));