Problem/Motivation

We want to use BinaryFileResponse implement CacheableResponseInterface.

But site crash and throw error 'Symfony\Component\HttpFoundation\File\File' is not allowed in serialize().

check PHP stack, it's from DynamicPageCacheSubscriber::onResponse()

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

CommentFileSizeAuthor
#4 3227041-4.patch1.3 KBOscaner
#2 3227041-2.patch1.25 KBOscaner

Comments

Oscaner created an issue. See original summary.

Oscaner’s picture

StatusFileSize
new1.25 KB
jeroent’s picture

Status: Needs work » Needs review
Oscaner’s picture

Version: 8.9.x-dev » 9.2.x-dev
StatusFileSize
new1.3 KB

Reroll on D9.2.x

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.1.10 (June 4, 2021) and Drupal 9.2.10 (November 24, 2021) were the last bugfix releases of those minor version series. Drupal 9 bug reports should be targeted for the 9.3.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

catch’s picture

Status: Needs review » Postponed (maintainer needs more info)
Issue tags: +Needs tests, +Needs issue summary update

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.

donquixote’s picture

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...

donquixote’s picture

Link to #3404512: Make the response cacheable for Media Alias Display.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

With the fix in for media alias display is this still needed?

smustgrave’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

Since the contrib module was fixed not sure this one is needed.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.