7

I have a url that would normally redirect to a specific page, however, some code is run prior to this. I am returning a RedirectResponse instance, and it appears to be being cached. How can I force this not to be cached?

3
  • Are you sure Drupal is doing the caching, because browsers will sometimes cache redirects.
    – mpdonadio
    Dec 2 '16 at 18:20
  • For me, it really was Drupal, as the RedirectResponse uses 302 which browsers shouldn't cache.
    – Gogowitsch
    Feb 8 '17 at 14:28
  • See related: drupal.stackexchange.com/questions/278698/…
    – sonfd
    Jun 19 '20 at 12:50
17

A response built from the RedirectReponse class is not cached. So you should not need to set any cache metadata. The problem here is probably the page cache for anonymous requests, which caches all responses, even redirects and no matter if they are cachable or not.

You can disable this cache by using the kill switch before returning the response:

\Drupal::service('page_cache_kill_switch')->trigger();

This will only disable the Internal Page Cache. To control caches outside of drupal, like proxies or browser caches, go to /admin/config/development/performance and set a "Page cache maximum age" or set response headers. See this comment How can I turn off caching redirect?

4
  • You can try that, but in redirect.module, we explicitly use cacheable redirect responses to have them cached. I think they aren't by default. As the comment from @mpdonadio says, this might actually be the browser doing the caching
    – Berdir
    Dec 2 '16 at 19:44
  • The class name in the question is the original Symfony redirect response without Drupal caching. For the browser cache see my edit.
    – 4k4
    Dec 3 '16 at 11:18
  • Yes, sorry, I was unclear. I meant those responses should actually not get cached, because to have them cached in redirect, we need to use a cacheable response.
    – Berdir
    Dec 3 '16 at 13:17
  • 1
    @Berdir RedirectResponseSubscriber changes ordinary RedirectResponse objects to LocalRedirectResponse objects which are cacheable. Nov 8 '18 at 23:48
1

As noted in the comments above, RedirectResponseSubscriber does alter redirects. Here's the relevant snippet:

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);
    }

So if you have a custom redirect that should not be cached, then create a custom class that extends SecuredRedirectResponse and implement the required isSafe() method. You may wish to leverage LocalAwareRedirectResponseTrait to use there to verify the url is local, along with any other check to verify that this is your redirect and not a mis-use. Your redirect will then skip the block above and not be converted to a cacheable redirect. Thanks to @smartsheet-eng for pointing me in the right direction.

1
  • This is not necessary. When this code is converting a RedirectResponse (not supporting cacheable metadata) it automatically adds a cache max-age of 0. See api.drupal.org/api/drupal/…
    – 4k4
    Nov 8 at 13:02
0

You may want to cache your response with CacheableRedirectResponse

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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