diff --git a/src/RequestHandler.php b/src/RequestHandler.php index d5f0efb..481a93d 100644 --- a/src/RequestHandler.php +++ b/src/RequestHandler.php @@ -31,7 +31,10 @@ use Drift\Console\TimeFormatter; use Drift\HttpKernel\AsyncKernel; use Drift\Server\Mime\MimeTypeChecker; +use React\Http\Io\HttpBodyStream; use function React\Promise\all; +use React\Promise\FulfilledPromise; +use React\Promise\Promise; use function React\Promise\resolve; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; @@ -41,10 +44,13 @@ use React\Promise\PromiseInterface; use React\Stream\ReadableStreamInterface; use React\Stream\ThroughStream; +use RingCentral\Psr7\BufferStream; use RingCentral\Psr7\Response as PSRResponse; +use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\File\UploadedFile as SymfonyUploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Throwable; @@ -268,35 +274,59 @@ private function toServerResponse( float $from ): PromiseInterface { if ($response instanceof Response) { - $response = new PSRResponse( - $response->getStatusCode(), - $response->headers->all(), - $response->getContent() - ); + if ($response instanceof BinaryFileResponse) { + $streamPromise = $this->filesystem->file($response->getFile()->getPathname())->open('r')->then(function (ReadableStreamInterface $stream) { + return new HttpBodyStream($stream, null); + }); + } elseif($response instanceof StreamedResponse) { + $streamPromise = new Promise(function($resolve, $reject) use($response) { + $stream = new BufferStream(); + $resolve($stream); + ob_start(function($data) use($stream, $resolve, &$isResolved) { + $stream->write($data); + }, 1); + $response->sendContent(); + ob_end_flush(); + }); + } else { + $streamPromise = new FulfilledPromise($response->getContent()); + } + + $responsePromise = $streamPromise->then(function ($stream) use($response) { + return new PSRResponse( + $response->getStatusCode(), + $response->headers->all(), + $stream + ); + }); + } else { + $responsePromise = new FulfilledPromise($response); } - return $this - ->applyResponseEncoding($response, $symfonyRequest->headers->get('Accept-Encoding')) - ->then(function (PSRResponse $response) use ($symfonyRequest, $from) { - $to = microtime(true); - $serverResponse = - new ServerResponseWithMessage( - $response, - $this->outputPrinter, - new ConsoleRequestMessage( - $symfonyRequest->getPathInfo(), - $symfonyRequest->getMethod(), - $response->getStatusCode(), - '', - TimeFormatter::formatTime($to - $from) - ) - ); - - $symfonyRequest = null; - $symfonyResponse = null; - - return $serverResponse; - }); + return $responsePromise->then(function (PSRResponse $response) use ($symfonyRequest, $from) { + return $this + ->applyResponseEncoding($response, $symfonyRequest->headers->get('Accept-Encoding')) + ->then(function (PSRResponse $response) use ($symfonyRequest, $from) { + $to = microtime(true); + $serverResponse = + new ServerResponseWithMessage( + $response, + $this->outputPrinter, + new ConsoleRequestMessage( + $symfonyRequest->getPathInfo(), + $symfonyRequest->getMethod(), + $response->getStatusCode(), + '', + TimeFormatter::formatTime($to - $from) + ) + ); + + $symfonyRequest = null; + $symfonyResponse = null; + + return $serverResponse; + }); + }); } /**