diff --git a/composer.json b/composer.json index 290d2bb..5e1f56e 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,8 @@ "nikic/fast-route": "^1.3", "react/async": "^4 || ^3", "react/http": "^1.10", - "react/promise": "^3 || ^2.10", - "react/socket": "^1.13" + "react/promise": "^3", + "react/socket": "^1.14" }, "require-dev": { "phpstan/phpstan": "1.10.47 || 1.4.10", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f688952..7e81cef 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -6,6 +6,3 @@ parameters: - tests/ reportUnmatchedIgnoredErrors: false - ignoreErrors: - # ignore generic usage like `PromiseInterface` until fixed upstream - - '/^PHPDoc tag @return contains generic type React\\Promise\\PromiseInterface but interface React\\Promise\\PromiseInterface is not generic\.$/' diff --git a/src/ErrorHandler.php b/src/ErrorHandler.php index e26d184..fbf9475 100644 --- a/src/ErrorHandler.php +++ b/src/ErrorHandler.php @@ -47,16 +47,8 @@ public function __invoke(ServerRequestInterface $request, callable $next) } else { return $this->errorInvalidResponse($response); } - }, function ($e) { - // Promise rejected, always a `\Throwable` as of Promise v3 - assert($e instanceof \Throwable || !\method_exists(PromiseInterface::class, 'catch')); // @phpstan-ignore-line - - if ($e instanceof \Throwable) { - return $this->errorInvalidException($e); - } else { // @phpstan-ignore-line - // @phpstan-ignore-next-line - return $this->errorInvalidResponse(\React\Promise\reject($e)); // @codeCoverageIgnore - } + }, function (\Throwable $e) { + return $this->errorInvalidException($e); }); } elseif ($response instanceof \Generator) { return $this->coroutine($response); diff --git a/tests/AppTest.php b/tests/AppTest.php index baf861c..a664012 100644 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -1272,32 +1272,6 @@ public function testInvokeWithMatchingRouteReturnsInternalServerErrorResponseWhe $this->assertStringContainsString("

Expected request handler to return Psr\Http\Message\ResponseInterface but got uncaught RuntimeException with message Foo in AppTest.php:$line.

\n", (string) $response->getBody()); } - public function testInvokeWithMatchingRouteReturnsInternalServerErrorResponseWhenHandlerReturnsPromiseWhichRejectsWithNull(): void - { - if (method_exists(PromiseInterface::class, 'catch')) { - $this->markTestSkipped('Only supported for legacy Promise v2, Promise v3 always rejects with Throwable'); - } - - $app = $this->createAppWithoutLogger(); - - $app->get('/users', function () { - return reject(null); // @phpstan-ignore-line - }); - - $request = new ServerRequest('GET', 'http://localhost/users'); - - $response = $app($request); - assert($response instanceof ResponseInterface); - - $this->assertEquals(500, $response->getStatusCode()); - $this->assertEquals('text/html; charset=utf-8', $response->getHeaderLine('Content-Type')); - $this->assertStringMatchesFormat("\n%a\n", (string) $response->getBody()); - - $this->assertStringContainsString("Error 500: Internal Server Error\n", (string) $response->getBody()); - $this->assertStringContainsString("

The requested page failed to load, please try again later.

\n", (string) $response->getBody()); - $this->assertStringContainsString("

Expected request handler to return Psr\Http\Message\ResponseInterface but got React\Promise\RejectedPromise.

\n", (string) $response->getBody()); - } - public function testInvokeWithMatchingRouteReturnsInternalServerErrorResponseWhenHandlerReturnsCoroutineWhichYieldsRejectedPromise(): void { $app = $this->createAppWithoutLogger(); diff --git a/tests/ErrorHandlerTest.php b/tests/ErrorHandlerTest.php index 96fb02a..739a5ce 100644 --- a/tests/ErrorHandlerTest.php +++ b/tests/ErrorHandlerTest.php @@ -271,33 +271,6 @@ public function testInvokeWithHandlerReturningPromiseResolvingWithNullReturnsPro $this->assertEquals(500, $response->getStatusCode()); } - public function testInvokeWithHandlerReturningPromiseRejectingWithNullReturnsPromiseResolvingWithError500Response(): void - { - if (method_exists(PromiseInterface::class, 'catch')) { - $this->markTestSkipped('Only supported for legacy Promise v2, Promise v3 always rejects with Throwable'); - } - - $handler = new ErrorHandler(); - - $request = new ServerRequest('GET', 'http://example.com/'); - - $promise = $handler($request, function () { - return reject(null); // @phpstan-ignore-line - }); - - /** @var PromiseInterface $promise */ - $this->assertInstanceOf(PromiseInterface::class, $promise); - - $response = null; - $promise->then(function ($value) use (&$response) { - $response = $value; - }); - - /** @var ResponseInterface $response */ - $this->assertInstanceOf(ResponseInterface::class, $response); - $this->assertEquals(500, $response->getStatusCode()); - } - public function testInvokeWithHandlerReturningGeneratorYieldingNullReturnsGeneratorYieldingError500Response(): void { $handler = new ErrorHandler(); diff --git a/tests/Io/ReactiveHandlerTest.php b/tests/Io/ReactiveHandlerTest.php index 18f13e0..a0c1b83 100644 --- a/tests/Io/ReactiveHandlerTest.php +++ b/tests/Io/ReactiveHandlerTest.php @@ -160,7 +160,6 @@ public function testRunWillListenForHttpRequestAndSendBackHttpResponseOverSocket $connector = new Connector(); $promise = $connector->connect($addr); - /** @var \React\Promise\PromiseInterface $promise */ $promise->then(function (ConnectionInterface $connection): void { $connection->on('data', function (string $data): void { $this->assertEquals("HTTP/1.0 200 OK\r\nContent-Length: 3\r\n\r\nOK\n", $data); @@ -217,7 +216,6 @@ public function testRunWillOnlyRestartLoopAfterAwaitingWhenFibersAreNotAvailable $logger->expects($this->never())->method('log'); } - /** @var \React\Promise\PromiseInterface $promise */ $promise->then(function (ConnectionInterface $connection): void { $connection->on('data', function (string $data): void { $this->assertEquals("HTTP/1.0 200 OK\r\nContent-Length: 3\r\n\r\nOK\n", $data); @@ -279,7 +277,6 @@ public function testRunWillReportHttpErrorForInvalidClientRequest(): void $connector = new Connector(); $promise = $connector->connect($addr); - /** @var \React\Promise\PromiseInterface $promise */ $promise->then(function (ConnectionInterface $connection) use ($logger): void { $logger->expects($this->once())->method('log')->with($this->matchesRegularExpression('/^HTTP error: .*$/')); $connection->write("not a valid HTTP request\r\n\r\n");