8000 [HttpFoundation] Every second request fails for BinaryFileResponse and non-modified file · Issue #47473 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content
[HttpFoundation] Every second request fails for BinaryFileResponse and non-modified file #47473
Closed
@stollr

Description

@stollr

Symfony version(s) affected

5.4.7 - 6.1.4

Description

Every second request to an action fails with the exception

You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".

How to reproduce

I can reproduce it with Symfony existing 5.4.7 project and a completely fresh 6.1.4 when no mime component is installed.

symfony new symfony6-test --version="6.1.*" --webapp
cd symfony6-test/
rm config/packages/messenger.yaml
composer remove symfony/mailer symfony/mime symfony/messenger

Then I have added a new controller with the following action:

    #[Route('/test', name: 'app_test')]
    public function index(Request $request): Response
    {
        $filename = $this->getParameter('kernel.project_dir').'/public/img/test.jpg';

        // Create cacheable response
        $response = new BinaryFileResponse($filename, 200, [
            'Content-Type' => 'image/jpeg', // <-- content type is set manually, here!
        ]);
        $response->setAutoLastModified();
        $response->isNotModified($request);

        return $response;
    }

Now, call the action in the browser multiple times. Every second you will get the above mentioned error.

Possible Solution

The issue is that Response::setNotModified() sets the status code to 304 and removes severall headers, including Content-Type.

In BinaryFileResponse::prepare() the mime type of the file is checked, if no content-type header is set. But in this case this is not desired.

What do you think about the following change?

    public function prepare(Request $request): static
    {
+        if (\in_array($this->getStatusCode(), [self::HTTP_NO_CONTENT, self::HTTP_NOT_MODIFIED])) {
+            return $this;
+        }
+
        if (!$this->headers->has('Content-Type')) {
            $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream');
        }
        // ...

As far as I see the whole code in the prepare method is irrelevant if no content is sent.

Additional Context

Exception backtrace:

LogicException:
You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".

  at vendor/symfony/http-foundation/File/File.php:74
  at Symfony\Component\HttpFoundation\File\File->getMimeType()
     (vendor/symfony/http-foundation/BinaryFileResponse.php:186)
  at Symfony\Component\HttpFoundation\BinaryFileResponse->prepare()
     (vendor/symfony/http-kernel/EventListener/ResponseListener.php:59)
  at Symfony\Component\HttpKernel\EventListener\ResponseListener->onKernelResponse()
     (vendor/symfony/event-dispatcher/Debug/WrappedListener.php:115)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0