Skip to content

Commit

Permalink
fix: RoadRunner streaming through generators (#939)
Browse files Browse the repository at this point in the history
* fix: RoadRunner streaming through generators

* Update RoadRunnerClient.php
  • Loading branch information
danharrin authored Aug 5, 2024
1 parent 4657dcf commit 2b5b4d0
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/RoadRunner/RoadRunnerClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Laravel\Octane\RoadRunner;

use Generator;
use Illuminate\Foundation\Application;
use Illuminate\Http\Request;
use Laravel\Octane\Contracts\Client;
Expand All @@ -10,6 +11,7 @@
use Laravel\Octane\Octane;
use Laravel\Octane\OctaneResponse;
use Laravel\Octane\RequestContext;
use ReflectionFunction;
use Spiral\RoadRunner\Http\PSR7Worker;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
Expand Down Expand Up @@ -47,6 +49,20 @@ public function respond(RequestContext $context, OctaneResponse $octaneResponse)
);
}

if (
($octaneResponse->response instanceof StreamedResponse) &&
($responseCallback = $octaneResponse->response->getCallback()) &&
((new ReflectionFunction($responseCallback))->getReturnType()?->getName() === Generator::class)
) {
$this->client->getHttpWorker()->respond(
$octaneResponse->response->getStatusCode(),
$responseCallback(),
$this->toPsr7Response($octaneResponse->response)->getHeaders(),
);

return;
}

$this->client->respond($this->toPsr7Response($octaneResponse->response));
}

Expand Down
29 changes: 29 additions & 0 deletions tests/RoadRunnerClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Laravel\Octane\Tests;

use Exception;
use Generator;
use Hamcrest\Core\IsInstanceOf;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Laminas\Diactoros\ServerRequestFactory;
Expand All @@ -11,6 +13,7 @@
use Laravel\Octane\RoadRunner\RoadRunnerClient;
use Mockery;
use Psr\Http\Message\ResponseInterface;
use Spiral\RoadRunner\Http\HttpWorker;
use Spiral\RoadRunner\Http\PSR7Worker;
use Symfony\Component\HttpFoundation\StreamedResponse;

Expand Down Expand Up @@ -63,6 +66,32 @@ public function test_respond_method_send_streamed_response_to_roadrunner()
}, 200)));
}

/** @doesNotPerformAssertions @test */
public function test_respond_method_send_streamed_generator_response_to_roadrunner()
{
$client = new RoadRunnerClient($psr7Client = Mockery::mock(PSR7Worker::class));

$psr7Request = (new ServerRequestFactory)->createServerRequest('GET', '/home');
$psr7Request = $psr7Request->withQueryParams(['name' => 'Taylor']);

$httpWorker = Mockery::mock(HttpWorker::class);

$responseCallback = function (): Generator {
yield 'Hello World';
};

$psr7Client->shouldReceive('getHttpWorker')->once()->andReturn($httpWorker);
$httpWorker->shouldReceive('respond')->once()->with(
200,
IsInstanceOf::anInstanceOf(Generator::class),
Mockery::hasKey('cache-control'),
);

$client->respond(new RequestContext([
'psr7Request' => $psr7Request,
]), new OctaneResponse(new StreamedResponse($responseCallback, 200)));
}

/** @doesNotPerformAssertions @test */
public function test_error_method_sends_error_response_to_roadrunner()
{
Expand Down

0 comments on commit 2b5b4d0

Please sign in to comment.