diff --git a/Makefile b/Makefile index c491a1b..6ab67c4 100755 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ phpstan: ## Run static analysis .PHONY: phpunit phpunit: ## Run unit tests - @phpunit --testdox --no-progress + @phpunit --testdox --no-progress --display-warnings .PHONY: coverage coverage: ## Code coverage diff --git a/src/Http/Middleware/ResponseMiddleware.php b/src/Http/Middleware/ResponseMiddleware.php index addf9ce..c317798 100644 --- a/src/Http/Middleware/ResponseMiddleware.php +++ b/src/Http/Middleware/ResponseMiddleware.php @@ -35,7 +35,14 @@ class ResponseMiddleware { $promise = new Promise( function (callable $resolve) use ($request, $next) { - $resolve($next($request)); + try { + $resolve($next($request)); + } catch (SecurityException $t) { + $resolve(Response::plaintext("Access Denied")->withStatus(Response::STATUS_UNAUTHORIZED)); + } catch (\Throwable $t) { + $this->logger->warning(get_class($t).": ".$t->getMessage(), [ 'file'=>$t->getFile(), 'line'=>$t->getLine() ]); + $resolve(Response::plaintext("500: Internal Server Error (".$t->getMessage().")\n")->withStatus(500)); + } } ); return $promise->then( @@ -50,19 +57,10 @@ class ResponseMiddleware return Response::plaintext($response); } return Response::plaintext((string)$response); - }, - function (Throwable $t) { - if ($t instanceof SecurityException) { - return Response::plaintext("Access Denied")->withStatus(Response::STATUS_UNAUTHORIZED); - } - $this->logger->warning(get_class($t).": ".$t->getMessage(), [ 'file'=>$t->getFile(), 'line'=>$t->getLine() ]); - return Response::plaintext("500: Internal Server Error (".$t->getMessage().")\n")->withStatus(500); } )->then( function ($response) use ($request) { assert("\$response instanceof ResponseInterface"); - $host = ($request->getServerParams()['SERVER_ADDR']??""); - //. ":" . ($request->getServerParams()['SERVER_PORT']??"80"); $this->logger->debug(sprintf("%s %s %s → %3d (%d)", $request->getServerParams()['REMOTE_ADDR'], $request->getMethod(), diff --git a/tests/Http/Middleware/ResponseMiddlewareTest.php b/tests/Http/Middleware/ResponseMiddlewareTest.php new file mode 100644 index 0000000..02c0870 --- /dev/null +++ b/tests/Http/Middleware/ResponseMiddlewareTest.php @@ -0,0 +1,62 @@ +'127.0.0.1']); + + $return = null; // chained response + + $next = function ($chainedRequest) use ($request, &$return) { + $this->assertInstanceOf(ServerRequestInterface::class, $chainedRequest); + $return = $chainedRequest; + return "response"; + }; + + $middleware = new ResponseMiddleware($config, $logger); + $middleware->__invoke($request, $next)->then(function ($result) { + $this->assertInstanceOf(Response::class, $result); + $this->assertEquals("response", $result->getBody()); + }); + } + + public function testSecurityExceptionsAreHandled() + { + $logger = new NullLogger(); + $config = Configuration::createDefault(); + + $request = new ServerRequest("GET", "/", serverParams:['REMOTE_ADDR'=>'127.0.0.1']); + + $return = null; // chained response + + $next = function ($chainedRequest) use ($request, &$return) { + $this->assertInstanceOf(ServerRequestInterface::class, $chainedRequest); + $return = $chainedRequest; + throw new SecurityException(); + }; + + $middleware = new ResponseMiddleware($config, $logger); + $middleware->__invoke($request, $next)->then(function ($result) { + $this->assertInstanceOf(Response::class, $result); + $this->assertEquals("Access Denied", (string)$result->getBody()); + }); + } + +} \ No newline at end of file