2

I am creating a custom module. In the routing.yml of the custom module, I have the following _permission and no_cache settings.

mymodule.test:
  path: '/mymodule/test'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::build'
    _title: 'Page Title'
  requirements:
    _permission: 'xxx authentication'
  options:
    no_cache: 'TRUE'

When anonymous users access this route, they will see the 403 page (Currently setting node content) configured in system.site.yml. This is a natural process.

However, the 403 page displayed is cached by Dynamic Page Cache. (Caching by Internal Page Cache is not confirmed at this time.)

The masked key is shown below(There is also a key when "session.exists" is 0).

response:[cookies:big_pipe_nojs]=:[languages:language_interface]=ja:[request_format]=html:[route]=entity.node.canonical<hash>:[session.exists]=1:[theme]=mytheme:[timezone]=Asia/Tokyo:[url.path]=/mymodule/test:[url.query_args:_wrapper_format]=:[url.site]=<site info>:[user.permissions]=<hash>:[user.roles]=anonymous

Is there any way to prevent Dynamic Page Cache from caching the 403 page?

1 Answer 1

1

You won't find a cache entry for a route with a no_cache option. The cache key is from a different route, probably the subrequest building the error page:

  • main request: [route]=mymodule.test
  • subrequest: [route]=entity.node.canonical

This should be no problem to cache the error page. This is like an error message "Access denied", only that is an entire HTML page, normally not containing dynamic content.

This is the answer so far, with the details the question provides. You can't reach the subrequest by adding the no_cache option to the main request route. You could add the same option to the node route as well, but this is certainly overkill. In most cases you don't even need the no_cache on routes at all, instead you add the necessary cache metadata inside of the request. The standard access denied exception is not cacheable by default, for advance use cases even http exceptions are now available as cacheable version and can transport cache metadata to the response. To be clear, this is all happening in the main request.

Since you are mentioning also the Internal Page Cache, this module is not suitable for dynamically created content, only for static database content. So uninstall this module in such use cases.


I just don't want to have 404 or 403 pages cached by Dynamic Page Cache. How can I configure it not to cache "only 403, 404 pages or 403, 404 node content", but not the entire node module?

Check in the subrequest whether the main request has set an exception attribute and then disable caching of the node:

function mymodule_preprocess_node(&$variables) {
  if (\Drupal::request()->attributes->has('exception')) {
    $variables['#cache']['max-age'] = 0;
    \Drupal::service('page_cache_kill_switch')->trigger();
  }
}

See HttpExceptionSubscriberBase::onException().

1
  • Thank you for your answer. I saw that the trigger is a node module, not a custom module. Thanks to your answer I knew it is not a problem. I just don't want to have 404 or 403 pages cached by Dynamic Page Cache. I don't think 'cache_ttl_4xx' in settings.php is the right solution as it is only valid for Internal Page Cache. How can I configure it not to cache "only 403, 404 pages or 403, 404 node content", but not the entire node module?
    – Skyyade
    Aug 1, 2022 at 5:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.