- 🇬🇧United Kingdom catch
What are you trying to cache BinaryFileResponse in that's not the dynamic page cache? BinaryFileResponse is a Symfony class and doesn't implement the interface, so would never enter the cache in the first place due to the CacheableResponse check in ::onRequest(). I'm not sure why we'd special case an interface that already doesn't implement CacheableResponseInterface by default.
If this is for custom code, you can add a dynamic page cache response policy to exclude BinaryFileResponse - that would allow you to implement the interface but still exclude it from dynamic page cache. I could see someone trying to do similar but also trying to make things serializable too, in which case the hard-coding of the interface here would prevent that.
Moving to needs more info until the use case is clearer.
- 🇩🇪Germany donquixote
I just ran into this.
The CacheableResponseInterface has two effects:
1. The page can be cached in Drupal's dynamic page cache.
2. The page gets cache tag headers and can be cached in Varnish.The Media Alias Display → module replaces the media controller and sends a BinaryFileResponse when visiting a media canonical url.
The module currently does not add any cache info to the response, making it uncacheable.
Our own varnish config auto-caches everything for anonymous for 8h.
This means that now these files are not purged on update, because Varnish does not have the cache tags.My solution attempt is to create this class:
declare(strict_types=1); namespace Drupal\media_alias_display\Response; use Drupal\Core\Cache\CacheableResponseInterface; use Drupal\Core\Cache\CacheableResponseTrait; use Symfony\Component\HttpFoundation\BinaryFileResponse; /** * A file response that can be cached. * * See https://www.drupal.org/project/drupal/issues/3227041. */ class CacheableBinaryFileResponse extends BinaryFileResponse implements CacheableResponseInterface { use CacheableResponseTrait; /** * Constructor. * * @param string $uri * File uri. * @param int $status * The http response code, e.g. 200 for "OK". * @param array $headers * An array of response headers. * @param bool $public * TRUE to set 'Cache-Control' header to 'public'. * FALSE to set 'Cache-Control' header to 'private'. * @param string|null $contentDisposition * A content-disposition header. * @param bool $autoEtag * TRUE to set an 'ETag' header based on the file checksum. * @param bool $autoLastModified * TRUE to set a 'Last-Modified' header based on the file mtime. */ public function __construct( protected string $uri, int $status = 200, array $headers = [], bool $public = TRUE, string $contentDisposition = NULL, bool $autoEtag = FALSE, bool $autoLastModified = TRUE, ) { parent::__construct($uri, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); } /** * Gets a serializable representation. * * @return array * Data for serialization. */ public function __serialize(): array { $values = (array) $this; // The file object cannot be serialized. unset($values["\0*\0file"]); return $values; } /** * Initializes uncacheable properties on unserialize. */ public function __wakeup(): void { $this->setFile($this->uri); } }
Now I only need to figure out which cache tags and cache contexts to add...
- 🇩🇪Germany donquixote
Link to 📌 Make the response cacheable Active for Media Alias Display.