Skip to content

Commit

Permalink
add response runner in frankenphp (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaume-sainthillier committed Nov 18, 2024
1 parent 2246529 commit 3e2f1e9
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 2 deletions.
49 changes: 49 additions & 0 deletions src/frankenphp-symfony/src/ResponseRunner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Runtime\FrankenPhpSymfony;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Runtime\RunnerInterface;

/**
* A response runner for FrankenPHP.
*
* @author Kévin Dunglas <kevin@dunglas.dev>
*/
class ResponseRunner implements RunnerInterface
{
public function __construct(
private Response $response,
private int $loopMax,
) {
}

public function run(): int
{
// Prevent worker script termination when a client connection is interrupted
ignore_user_abort(true);

$server = array_filter($_SERVER, static fn (string $key) => !str_starts_with($key, 'HTTP_'), ARRAY_FILTER_USE_KEY);
$server['APP_RUNTIME_MODE'] = 'web=1&worker=1';

$handler = function () use ($server, &$sfRequest): void {

Check failure on line 32 in src/frankenphp-symfony/src/ResponseRunner.php

View workflow job for this annotation

GitHub Actions / Psalm

UndefinedVariable

src/frankenphp-symfony/src/ResponseRunner.php:32:47: UndefinedVariable: Cannot find referenced variable $sfRequest (see https://psalm.dev/024)
// Merge the environment variables coming from DotEnv with the ones tied to the current request
$_SERVER += $server;

$sfRequest = Request::createFromGlobals();
$this->response->send();
};

$loops = 0;
do {
$ret = \frankenphp_handle_request($handler);

Check failure on line 42 in src/frankenphp-symfony/src/ResponseRunner.php

View workflow job for this annotation

GitHub Actions / PHPStan

Function frankenphp_handle_request not found.

gc_collect_cycles();
} while ($ret && (-1 === $this->loopMax || ++$loops < $this->loopMax));

return 0;
}
}
11 changes: 9 additions & 2 deletions src/frankenphp-symfony/src/Runtime.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Runtime\FrankenPhpSymfony;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Runtime\RunnerInterface;
use Symfony\Component\Runtime\SymfonyRuntime;
Expand All @@ -29,8 +30,14 @@ public function __construct(array $options = [])

public function getRunner(?object $application): RunnerInterface
{
if ($application instanceof HttpKernelInterface && ($_SERVER['FRANKENPHP_WORKER'] ?? false)) {
return new Runner($application, $this->options['frankenphp_loop_max']);
if ($_SERVER['FRANKENPHP_WORKER'] ?? false) {
if ($application instanceof HttpKernelInterface) {
return new Runner($application, $this->options['frankenphp_loop_max']);
}

if ($application instanceof Response) {
return new ResponseRunner($application, $this->options['frankenphp_loop_max']);
}
}

return parent::getRunner($application);
Expand Down
12 changes: 12 additions & 0 deletions src/frankenphp-symfony/tests/RunnerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require_once __DIR__.'/function-mock.php';

use PHPUnit\Framework\TestCase;
use Runtime\FrankenPhpSymfony\ResponseRunner;
use Runtime\FrankenPhpSymfony\Runner;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -22,6 +23,17 @@ interface TestAppInterface extends HttpKernelInterface, TerminableInterface
*/
class RunnerTest extends TestCase
{
public function testResponseRun(): void
{
$application = $this->createMock(Response::class);
$application
->expects($this->once())
->method('send');

$runner = new ResponseRunner($application, 500);
$this->assertSame(0, $runner->run());
}

public function testRun(): void
{
$application = $this->createMock(TestAppInterface::class);
Expand Down
16 changes: 16 additions & 0 deletions src/frankenphp-symfony/tests/RuntimeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
namespace Runtime\FrankenPhpSymfony\Tests;

use PHPUnit\Framework\TestCase;
use Runtime\FrankenPhpSymfony\ResponseRunner;
use Runtime\FrankenPhpSymfony\Runner;
use Runtime\FrankenPhpSymfony\Runtime;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;

/**
Expand All @@ -16,6 +18,7 @@ final class RuntimeTest extends TestCase
{
public function testGetRunner(): void
{
unset($_SERVER['FRANKENPHP_WORKER']);
$application = $this->createStub(HttpKernelInterface::class);

$runtime = new Runtime();
Expand All @@ -25,4 +28,17 @@ public function testGetRunner(): void
$_SERVER['FRANKENPHP_WORKER'] = 1;
$this->assertInstanceOf(Runner::class, $runtime->getRunner($application));
}

public function testGetResponseRunner(): void
{
unset($_SERVER['FRANKENPHP_WORKER']);
$application = $this->createStub(Response::class);

$runtime = new Runtime();
$this->assertNotInstanceOf(ResponseRunner::class, $runtime->getRunner(null));
$this->assertNotInstanceOf(ResponseRunner::class, $runtime->getRunner($application));

$_SERVER['FRANKENPHP_WORKER'] = 1;
$this->assertInstanceOf(ResponseRunner::class, $runtime->getRunner($application));
}
}

0 comments on commit 3e2f1e9

Please sign in to comment.