11

I try in annotation

 * @Cache(expires="+10 hours", public=false) 

or in controller

$maxAge = 60*60;
$response->setExpires(Carbon::create()->addHour());
$response->setSharedMaxAge($maxAge);
$response->setPublic();
$response->setMaxAge($maxAge);

And still have Cache-Control: max-age=0, must-revalidate, private

App use sessions, user is login - I want - cache private, but nothing work - I always get this.

I've added FOS\HttpCacheBundle\FOSHttpCacheBundle()

(just add) Have hope to it override symfony cache and allow send cache private - but nothing change.

4 Answers 4

23

This behaviour is new as of Symfony 3.4 and 4.0. If a user session has been initialized it will always set the headers as described in your question.

Introduced in Symfony 4.1 you can override this behaviour. However as this is a new feature this will not be backported to Symfony 3.4.

$response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');

You can read about this in the Symfony documentation: HTTP Caching and User Sessions

Sign up to request clarification or add additional context in comments.

2 Comments

Am I reading this wrong, or this means that in v3.4, it is not possible to use the ESI with HTTP Cache, as long as you have an active user session?
Apparently you are reading it right. This is a non-trivial B/C break for ESI-based setups, one can even not cache responses that are user-agnostic when session cookie exists (regardless of the actual login state). Bug report: github.com/symfony/symfony/issues/29151
4

Probably the best way to do this would be to use Service decoration, but i prefered the dirty way for now.

In my case i just needed the shared cached headers for a specific controller.

Workaroung for Symfony 3.4.*:

Create a listener with lower priority than Symfony\Component\HttpKernel\EventListener\SessionListener in services.yml (don't know if this is recommended):

AppBundle\Listener\ResponseListener:
    tags:
        - { name: kernel.event_listener, event: kernel.response, priority: -1001 }

Then in AppBundle\Listener\ResponseListener:

<?php

namespace AppBundle\Listener;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;

class ResponseListener
{
    public function onKernelResponse(FilterResponseEvent $event)
    {
        $response = $event->getResponse();

        $controller = $event->getRequest()->attributes->get('_controller');
        $requiredAssetAction = "AppBundle\Controller\Website\AssetsController::assetAction";

        if ($controller == $requiredAssetAction) {
            $response->headers->addCacheControlDirective('max-age', 900);
            $response->headers->addCacheControlDirective('s-maxage', 900);
            $response->headers->addCacheControlDirective('must-revalidate', true);
            $response->headers->addCacheControlDirective('public', true);
            $response->headers->removeCacheControlDirective('private');

        }

        $event->setResponse($response);
    }

}

1 Comment

Excellent answer! You can apply the changes to a whole controller using if (strpos($controller, 'AssetController') !== false)
0

Are you using a reverse proxy like the Symfony one? https://symfony.com/doc/3.4/http_cache.html#symfony-reverse-proxy

Also, in your example, the annotation has public=false while the controller will have public true.

Another possible problem would be that your webserver (Apatche etc) is configured to add that header or an option in your .htaccess file specifies this.

Comments

0

I worked around this in a legacy 3.4 application by simply implementing the logic from the AbstractSessionListener and SessionListener classes from the symfony/http-kernel component in my own listener and overwriting the service with an alias to my own implementation:

  session_listener:
    alias: 'Vendored\Symfony\EventSubscriber\SessionListener'
    tags:
      - { name: 'kernel.event_subscriber' }

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.