Baldinof / roadrunner-bundle

A RoadRunner worker integrated in your Symfony app
MIT License
255 stars 46 forks source link

It's impossible to send big files/responses #101

Closed FluffyDiscord closed 1 year ago

FluffyDiscord commented 1 year ago

I was wondering why my custom class extending Symfony'sBinaryFileResponse did not call public function sendContent(): static and I found the reason and it's concerning.

https://github.com/Baldinof/roadrunner-bundle/blob/2.x/src/RoadRunnerBridge/HttpFoundationWorker.php

public function respond(SymfonyResponse $symfonyResponse): void
    {
        if ($symfonyResponse instanceof BinaryFileResponse && !$symfonyResponse->headers->has('Content-Range')) {
            $content = file_get_contents($symfonyResponse->getFile()->getPathname());
            if ($content === false) {
                throw new \RuntimeException(sprintf("Cannot read file '%s'", $symfonyResponse->getFile()->getPathname())); // TODO: custom error
            }
        } else {
            if ($symfonyResponse instanceof StreamedResponse || $symfonyResponse instanceof BinaryFileResponse) {
                $content = '';
                ob_start(function ($buffer) use (&$content) {
                    $content .= $buffer;

                    return '';
                });

                $symfonyResponse->sendContent();
                ob_end_clean();
            } else {
                $content = (string) $symfonyResponse->getContent();
            }
        }

        $headers = $this->stringifyHeaders($symfonyResponse->headers->all());

        $this->httpWorker->respond($symfonyResponse->getStatusCode(), $content, $headers);
    }

The bundle reads the whole file into RAM and then sends it to the RR. The main issue is that you can not send bigger files/payloads than your max_memory_limit. I can not increase my limit to 30GB to send back huge archives, because I don't have that much RAM available.

Can something be done please?

Baldinof commented 1 year ago

Hello!

This is on purpose because RoadRunner does not support streaming responses (see the feature request).

There is not much that can be done now, if your file cannot fit into memory I would suggest you to stick with php-fpm.