diff --git a/src/Runtime/Octane/Octane.php b/src/Runtime/Octane/Octane.php index bccf174..774d162 100644 --- a/src/Runtime/Octane/Octane.php +++ b/src/Runtime/Octane/Octane.php @@ -23,6 +23,7 @@ use Laravel\Vapor\Runtime\StorageDirectories; use PDO; use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Symfony\Component\HttpFoundation\StreamedResponse; use Throwable; class Octane implements Client @@ -166,6 +167,10 @@ public static function handle($request) ? $response->getFile()->getContent() : $response->getContent(); + if ($response instanceof StreamedResponse) { + $content = static::captureContent($response); + } + return tap(new Response( $content, $response->headers->all(), @@ -284,4 +289,17 @@ public static function worker() { return static::$worker; } + + /** + * Capture the content from a streamed response. + */ + protected static function captureContent(StreamedResponse $response): string + { + ob_start(); + $response->sendContent(); + $content = ob_get_contents(); + ob_end_clean(); + + return $content; + } } diff --git a/tests/Feature/ApiGatewayOctaneHandlerTest.php b/tests/Feature/ApiGatewayOctaneHandlerTest.php index 48c74dc..6b9300b 100644 --- a/tests/Feature/ApiGatewayOctaneHandlerTest.php +++ b/tests/Feature/ApiGatewayOctaneHandlerTest.php @@ -17,6 +17,7 @@ use Laravel\Vapor\Tests\TestCase; use Mockery; use RuntimeException; +use Symfony\Component\HttpFoundation\StreamedResponse; class ApiGatewayOctaneHandlerTest extends TestCase { @@ -601,4 +602,24 @@ public function test_maintenance_mode_with_invalid_bypass_cookie() static::assertEquals('application/json', $response->toApiGatewayFormat()['headers']['Content-Type']); static::assertEquals(['message' => 'We are currently down for maintenance.'], json_decode($response->toApiGatewayFormat()['body'], true)); } + + public function test_streamed_responses() + { + $handler = new OctaneHandler(); + + Route::get('/', function () { + return new StreamedResponse(function () { + echo 'Hello World'; + }, 200, ['mime-type' => 'image/png']); + }); + + $response = $handler->handle([ + 'httpMethod' => 'GET', + 'path' => '/', + 'headers' => [], + ]); + + static::assertEquals('image/png', $response->toApiGatewayFormat()['headers']['Mime-Type']); + static::assertEquals('Hello World', $response->toApiGatewayFormat()['body']); + } } diff --git a/tests/Feature/LoadBalancedOctaneHandlerTest.php b/tests/Feature/LoadBalancedOctaneHandlerTest.php index 5ec80fe..0a9fd40 100644 --- a/tests/Feature/LoadBalancedOctaneHandlerTest.php +++ b/tests/Feature/LoadBalancedOctaneHandlerTest.php @@ -17,6 +17,7 @@ use Laravel\Vapor\Tests\TestCase; use Mockery; use RuntimeException; +use Symfony\Component\HttpFoundation\StreamedResponse; class LoadBalancedOctaneHandlerTest extends TestCase { @@ -599,4 +600,26 @@ public function test_maintenance_mode_with_invalid_bypass_cookie() static::assertEquals(['application/json'], $response->toApiGatewayFormat()['multiValueHeaders']['Content-Type']); static::assertEquals(['message' => 'We are currently down for maintenance.'], json_decode($response->toApiGatewayFormat()['body'], true)); } + + public function test_streamed_responses() + { + $handler = new LoadBalancedOctaneHandler(); + + Route::get('/', function () { + return new StreamedResponse(function () { + echo 'Hello World'; + }, 200, ['mime-type' => 'image/png']); + }); + + $response = $handler->handle([ + 'httpMethod' => 'GET', + 'path' => '/', + 'headers' => [ + 'Accept' => 'application/json', + ], + ]); + + static::assertEquals(['image/png'], $response->toApiGatewayFormat()['multiValueHeaders']['Mime-Type']); + static::assertEquals('Hello World', $response->toApiGatewayFormat()['body']); + } }