From 8964184c454afd494572e091c965b4a1cad3c758 Mon Sep 17 00:00:00 2001 From: Sascha Date: Wed, 22 Oct 2025 09:52:29 +0200 Subject: [PATCH 1/2] feat: add middleware to FrankenPhpSymfony --- .../Exception/InvalidMiddlewareException.php | 20 ++++++ .../src/Middleware/MiddlewareInterface.php | 10 +++ src/frankenphp-symfony/src/Runner.php | 15 ++++ src/frankenphp-symfony/src/Runtime.php | 2 + src/frankenphp-symfony/tests/RunnerTest.php | 68 ++++++++++++++++--- .../tests/Support/InvalidMiddleware.php | 8 +++ .../tests/Support/TestMiddleware.php | 28 ++++++++ 7 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php create mode 100644 src/frankenphp-symfony/src/Middleware/MiddlewareInterface.php create mode 100644 src/frankenphp-symfony/tests/Support/InvalidMiddleware.php create mode 100644 src/frankenphp-symfony/tests/Support/TestMiddleware.php diff --git a/src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php b/src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php new file mode 100644 index 00000000..02e773fd --- /dev/null +++ b/src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php @@ -0,0 +1,20 @@ +send(); }; + foreach ($this->middlewares as $middlewareClass) { + if (!is_a($middlewareClass, MiddlewareInterface::class, true)) { + throw new InvalidMiddlewareException($middlewareClass, 1761117929733); + } + + $middleware = new $middlewareClass(); + $handler = fn () => $middleware->wrap($handler, $server); + } + $loops = 0; do { $ret = \frankenphp_handle_request($handler); diff --git a/src/frankenphp-symfony/src/Runtime.php b/src/frankenphp-symfony/src/Runtime.php index efae98bc..1e665475 100644 --- a/src/frankenphp-symfony/src/Runtime.php +++ b/src/frankenphp-symfony/src/Runtime.php @@ -23,6 +23,8 @@ class Runtime extends SymfonyRuntime public function __construct(array $options = []) { $options['frankenphp_loop_max'] = (int) ($options['frankenphp_loop_max'] ?? $_SERVER['FRANKENPHP_LOOP_MAX'] ?? $_ENV['FRANKENPHP_LOOP_MAX'] ?? 500); + $options['frankenphp_middlewares'] = (string) ($options['frankenphp_middlewares'] ?? $_SERVER['FRANKENPHP_MIDDLEWARES'] ?? $_ENV['FRANKENPHP_MIDDLEWARES'] ?? ''); + $options['frankenphp_middlewares'] = array_filter(explode("\n", $options['frankenphp_middlewares'])); parent::__construct($options); } diff --git a/src/frankenphp-symfony/tests/RunnerTest.php b/src/frankenphp-symfony/tests/RunnerTest.php index 8d3caa76..0c0560e8 100644 --- a/src/frankenphp-symfony/tests/RunnerTest.php +++ b/src/frankenphp-symfony/tests/RunnerTest.php @@ -4,10 +4,13 @@ namespace Runtime\FrankenPhpSymfony\Tests; -require_once __DIR__.'/function-mock.php'; +require_once __DIR__ . '/function-mock.php'; use PHPUnit\Framework\TestCase; +use Runtime\FrankenPhpSymfony\Exception\InvalidMiddlewareException; use Runtime\FrankenPhpSymfony\Runner; +use Runtime\FrankenPhpSymfony\Tests\Support\InvalidMiddleware; +use Runtime\FrankenPhpSymfony\Tests\Support\TestMiddleware; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; @@ -22,22 +25,65 @@ interface TestAppInterface extends HttpKernelInterface, TerminableInterface */ class RunnerTest extends TestCase { - public function testRun(): void + + static function runData(): iterable { + yield 'basic' => []; + yield 'middleware' => [ + 'middleware' => TestMiddleware::class + ]; + yield 'Invalid middleware' => [ + 'middleware' => InvalidMiddleware::class, + 'expectException' => InvalidMiddlewareException::class + ]; + } + + /** + * @dataProvider runData + */ + public function testRun( + ?string $middleware = null, + ?string $expectException = null + ): void { + if ($expectException !== null) { + $this->expectException($expectException); + } + $application = $this->createMock(TestAppInterface::class); - $application - ->expects($this->once()) - ->method('handle') - ->willReturnCallback(function (Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true): Response { - $this->assertSame('bar', $request->server->get('FOO')); - return new Response(); - }); - $application->expects($this->once())->method('terminate'); + if ($expectException === null) { + $application + ->expects($this->once()) + ->method('handle') + ->willReturnCallback( + function ( + Request $request, + int $type = HttpKernelInterface::MAIN_REQUEST, + bool $catch = true + ): Response { + $this->assertSame('bar', $request->server->get('FOO')); + + return new Response(); + } + ); + $application->expects($this->once())->method('terminate'); + } $_SERVER['FOO'] = 'bar'; - $runner = new Runner($application, 500); + $runner = new Runner($application, 500, array_filter([ + $middleware + ])); + + $assertMiddlewareInvoked = $expectException === null && $middleware && method_exists($middleware, 'isInvoked'); + if ($assertMiddlewareInvoked) { + $this->assertFalse($middleware::isInvoked()); + } + $this->assertSame(0, $runner->run()); + + if ($assertMiddlewareInvoked) { + $this->assertTrue($middleware::isInvoked()); + } } } diff --git a/src/frankenphp-symfony/tests/Support/InvalidMiddleware.php b/src/frankenphp-symfony/tests/Support/InvalidMiddleware.php new file mode 100644 index 00000000..55b5ea12 --- /dev/null +++ b/src/frankenphp-symfony/tests/Support/InvalidMiddleware.php @@ -0,0 +1,8 @@ + Date: Wed, 22 Oct 2025 10:05:59 +0200 Subject: [PATCH 2/2] fix: static analysis issues --- .../Exception/InvalidMiddlewareException.php | 11 +++----- .../src/Middleware/MiddlewareInterface.php | 2 +- src/frankenphp-symfony/src/Runtime.php | 1 + src/frankenphp-symfony/tests/RunnerTest.php | 27 +++++++++---------- .../tests/Support/InvalidMiddleware.php | 3 ++- .../tests/Support/TestMiddleware.php | 2 +- 6 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php b/src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php index 02e773fd..cc34f2eb 100644 --- a/src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php +++ b/src/frankenphp-symfony/src/Exception/InvalidMiddlewareException.php @@ -1,16 +1,13 @@ []; + yield 'middleware' => [ - 'middleware' => TestMiddleware::class + 'middleware' => TestMiddleware::class, ]; + yield 'Invalid middleware' => [ 'middleware' => InvalidMiddleware::class, - 'expectException' => InvalidMiddlewareException::class + 'expectException' => InvalidMiddlewareException::class, ]; } @@ -43,15 +44,11 @@ static function runData(): iterable */ public function testRun( ?string $middleware = null, - ?string $expectException = null + ?string $expectException = null, ): void { - if ($expectException !== null) { - $this->expectException($expectException); - } - $application = $this->createMock(TestAppInterface::class); - if ($expectException === null) { + if (null === $expectException) { $application ->expects($this->once()) ->method('handle') @@ -67,15 +64,15 @@ function ( } ); $application->expects($this->once())->method('terminate'); + } else { + $this->expectException($expectException); } $_SERVER['FOO'] = 'bar'; - $runner = new Runner($application, 500, array_filter([ - $middleware - ])); + $runner = new Runner($application, 500, array_filter([$middleware])); - $assertMiddlewareInvoked = $expectException === null && $middleware && method_exists($middleware, 'isInvoked'); + $assertMiddlewareInvoked = null === $expectException && $middleware && method_exists($middleware, 'isInvoked'); if ($assertMiddlewareInvoked) { $this->assertFalse($middleware::isInvoked()); } diff --git a/src/frankenphp-symfony/tests/Support/InvalidMiddleware.php b/src/frankenphp-symfony/tests/Support/InvalidMiddleware.php index 55b5ea12..356dbdec 100644 --- a/src/frankenphp-symfony/tests/Support/InvalidMiddleware.php +++ b/src/frankenphp-symfony/tests/Support/InvalidMiddleware.php @@ -1,8 +1,9 @@