Unverified Commit b7b2a8be authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3049048 by danflanagan8, ndobromirov, mglaman, bbrala, alexpott, Wim...

Issue #3049048 by danflanagan8, ndobromirov, mglaman, bbrala, alexpott, Wim Leers, gabesullice: Invalid JSON:API responses when maintenance mode is on
parent 4f4f390b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1229,10 +1229,10 @@ services:
      - { name: access_check, needs_incoming_request: TRUE }
  maintenance_mode:
    class: Drupal\Core\Site\MaintenanceMode
    arguments: ['@state']
    arguments: ['@state', '@config.factory']
  maintenance_mode_subscriber:
    class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber
    arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer', '@messenger']
    arguments: ['@maintenance_mode', '@config.factory', '@string_translation', '@url_generator', '@current_user', '@bare_html_page_renderer', '@messenger', '@event_dispatcher']
    tags:
      - { name: event_subscriber }
  route_access_response_subscriber:
+40 −24
Original line number Diff line number Diff line
@@ -2,13 +2,13 @@

namespace Drupal\Core\EventSubscriber;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Render\BareHtmlPageRendererInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Render\BareHtmlPageRendererInterface;
use Drupal\Core\Routing\RouteMatch;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\MaintenanceModeEvents;
use Drupal\Core\Site\MaintenanceModeInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
@@ -16,6 +16,7 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
 * Maintenance mode subscriber for controller requests.
@@ -66,6 +67,13 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
   */
  protected $messenger;

  /**
   * An event dispatcher instance to use for configuration events.
   *
   * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface
   */
  protected $eventDispatcher;

  /**
   * Constructs a new MaintenanceModeSubscriber.
   *
@@ -83,8 +91,10 @@ class MaintenanceModeSubscriber implements EventSubscriberInterface {
   *   The bare HTML page renderer.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   * @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $event_dispatcher
   *   The event dispatcher.
   */
  public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer, MessengerInterface $messenger) {
  public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFactoryInterface $config_factory, TranslationInterface $translation, UrlGeneratorInterface $url_generator, AccountInterface $account, BareHtmlPageRendererInterface $bare_html_page_renderer, MessengerInterface $messenger, EventDispatcherInterface $event_dispatcher = NULL) {
    $this->maintenanceMode = $maintenance_mode;
    $this->config = $config_factory;
    $this->stringTranslation = $translation;
@@ -92,6 +102,11 @@ public function __construct(MaintenanceModeInterface $maintenance_mode, ConfigFa
    $this->account = $account;
    $this->bareHtmlPageRenderer = $bare_html_page_renderer;
    $this->messenger = $messenger;
    if (!$event_dispatcher) {
      @trigger_error('Calling MaintenanceModeSubscriber::__construct() without the $event_dispatcher argument is deprecated in drupal:9.4.0 and the $event_dispatcher argument will be required in drupal:10.0.0. See https://www.drupal.org/node/3255799', E_USER_DEPRECATED);
      $event_dispatcher = \Drupal::service('event_dispatcher');
    }
    $this->eventDispatcher = $event_dispatcher;
  }

  /**
@@ -108,20 +123,8 @@ public function onKernelRequestMaintenance(RequestEvent $event) {
      \Drupal::service('page_cache_kill_switch')->trigger();

      if (!$this->maintenanceMode->exempt($this->account)) {
        // Deliver the 503 page if the site is in maintenance mode and the
        // logged in user is not allowed to bypass it.

        // If the request format is not 'html' then show default maintenance
        // mode page else show a text/plain page with maintenance message.
        if ($request->getRequestFormat() !== 'html') {
          $response = new Response($this->getSiteMaintenanceMessage(), 503, ['Content-Type' => 'text/plain']);
          $event->setResponse($response);
          return;
        }
        drupal_maintenance_theme();
        $response = $this->bareHtmlPageRenderer->renderBarePage(['#markup' => $this->getSiteMaintenanceMessage()], $this->t('Site under maintenance'), 'maintenance_page');
        $response->setStatusCode(503);
        $event->setResponse($response);
        // When the account is not exempt, other subscribers handle request.
        $this->eventDispatcher->dispatch($event, MaintenanceModeEvents::MAINTENANCE_MODE_REQUEST);
      }
      else {
        // Display a message if the logged in user has access to the site in
@@ -140,15 +143,24 @@ public function onKernelRequestMaintenance(RequestEvent $event) {
  }

  /**
   * Gets the site maintenance message.
   * Returns response when site is in maintenance mode and user is not exempt.
   *
   * @return \Drupal\Component\Render\MarkupInterface
   *   The formatted site maintenance message.
   * @param \Symfony\Component\HttpKernel\Event\RequestEvent $event
   *   The event to process.
   */
  protected function getSiteMaintenanceMessage() {
    return new FormattableMarkup($this->config->get('system.maintenance')->get('message'), [
      '@site' => $this->config->get('system.site')->get('name'),
    ]);
  public function onMaintenanceModeRequest(RequestEvent $event) {
    $request = $event->getRequest();
    if ($request->getRequestFormat() !== 'html') {
      $response = new Response($this->maintenanceMode->getSiteMaintenanceMessage(), 503, ['Content-Type' => 'text/plain']);
      // Calling RequestEvent::setResponse() also stops propagation of event.
      $event->setResponse($response);
      return;
    }
    drupal_maintenance_theme();
    $response = $this->bareHtmlPageRenderer->renderBarePage(['#markup' => $this->maintenanceMode->getSiteMaintenanceMessage()], $this->t('Site under maintenance'), 'maintenance_page');
    $response->setStatusCode(503);
    // Calling RequestEvent::setResponse() also stops propagation of the event.
    $event->setResponse($response);
  }

  /**
@@ -157,6 +169,10 @@ protected function getSiteMaintenanceMessage() {
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['onKernelRequestMaintenance', 30];
    $events[KernelEvents::EXCEPTION][] = ['onKernelRequestMaintenance'];
    $events[MaintenanceModeEvents::MAINTENANCE_MODE_REQUEST][] = [
      'onMaintenanceModeRequest',
      -1000,
    ];
    return $events;
  }

+26 −1
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@

namespace Drupal\Core\Site;

use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\State\StateInterface;
@@ -18,14 +20,28 @@ class MaintenanceMode implements MaintenanceModeInterface {
   */
  protected $state;

  /**
   * The configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $config;

  /**
   * Constructs a new maintenance mode service.
   *
   * @param \Drupal\Core\State\StateInterface $state
   *   The state.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   */
  public function __construct(StateInterface $state) {
  public function __construct(StateInterface $state, ConfigFactoryInterface $config_factory = NULL) {
    $this->state = $state;
    if (!$config_factory) {
      @trigger_error('Calling MaintenanceMode::__construct() without the $config_factory argument is deprecated in drupal:9.4.0 and the $config_factory argument will be required in drupal:10.0.0. See https://www.drupal.org/node/3255815', E_USER_DEPRECATED);
      $config_factory = \Drupal::service('config.factory');
    }
    $this->config = $config_factory;
  }

  /**
@@ -52,4 +68,13 @@ public function exempt(AccountInterface $account) {
    return $account->hasPermission('access site in maintenance mode');
  }

  /**
   * {@inheritdoc}
   */
  public function getSiteMaintenanceMessage() {
    return new FormattableMarkup($this->config->get('system.maintenance')->get('message'), [
      '@site' => $this->config->get('system.site')->get('name'),
    ]);
  }

}
+15 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Core\Site;

/**
 * Defines events for maintenance mode.
 */
final class MaintenanceModeEvents {

  /**
   * The name of the event fired when request is made in maintenance more.
   */
  const MAINTENANCE_MODE_REQUEST = 'site.maintenance_mode_request';

}
+8 −0
Original line number Diff line number Diff line
@@ -32,4 +32,12 @@ public function applies(RouteMatchInterface $route_match);
   */
  public function exempt(AccountInterface $account);

  /**
   * Gets the site maintenance message.
   *
   * @return \Drupal\Component\Render\MarkupInterface
   *   The formatted site maintenance message.
   */
  public function getSiteMaintenanceMessage();

}
Loading