Browse Source

Update ErrorHandlerMiddleware to PSR 15 standard.

ADmad 7 years ago
parent
commit
ae99e9a392

+ 17 - 18
src/Error/Middleware/ErrorHandlerMiddleware.php

@@ -21,9 +21,13 @@ use Cake\Core\Exception\Exception as CakeException;
 use Cake\Core\InstanceConfigTrait;
 use Cake\Error\ExceptionRenderer;
 use Cake\Error\ExceptionRendererInterface;
+use Cake\Http\Response;
 use Cake\Log\Log;
 use Exception;
+use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
 use Throwable;
 
 /**
@@ -34,7 +38,7 @@ use Throwable;
  *
  * @mixin \Cake\Core\InstanceConfigTrait
  */
-class ErrorHandlerMiddleware
+class ErrorHandlerMiddleware implements MiddlewareInterface
 {
     use InstanceConfigTrait;
 
@@ -92,16 +96,15 @@ class ErrorHandlerMiddleware
      * Wrap the remaining middleware with error handling.
      *
      * @param \Psr\Http\Message\ServerRequestInterface $request The request.
-     * @param \Psr\Http\Message\ResponseInterface $response The response.
-     * @param callable $next Callback to invoke the next middleware.
-     * @return \Psr\Http\Message\ResponseInterface A response
+     * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler.
+     * @return \Cake\Http\ResponseInterface A response.
      */
-    public function __invoke($request, $response, $next)
+    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
         try {
-            return $next($request, $response);
+            return $handler->handle($request);
         } catch (Throwable $exception) {
-            return $this->handleException($exception, $request, $response);
+            return $this->handleException($exception, $request);
         }
     }
 
@@ -110,10 +113,9 @@ class ErrorHandlerMiddleware
      *
      * @param \Throwable $exception The exception to handle.
      * @param \Psr\Http\Message\ServerRequestInterface $request The request.
-     * @param \Psr\Http\Message\ResponseInterface $response The response.
      * @return \Psr\Http\Message\ResponseInterface A response
      */
-    public function handleException($exception, $request, $response)
+    public function handleException($exception, $request)
     {
         $renderer = $this->getRenderer($exception, $request);
         try {
@@ -122,26 +124,23 @@ class ErrorHandlerMiddleware
 
             return $res;
         } catch (Throwable $exception) {
-            $this->logException($request, $exception);
-            $response = $this->handleInternalError($response);
         }
 
-        return $response;
+        $this->logException($request, $exception);
+
+        return $this->handleInternalError();
     }
 
     /**
      * Handle internal errors.
      *
-     * @param \Psr\Http\Message\ResponseInterface $response The response
      * @return \Psr\Http\Message\ResponseInterface A response
      */
-    protected function handleInternalError($response)
+    protected function handleInternalError()
     {
-        $body = $response->getBody();
-        $body->write('An Internal Server Error Occurred');
+        $response = new Response(['body' => 'An Internal Server Error Occurred']);
 
-        return $response->withStatus(500)
-            ->withBody($body);
+        return $response->withStatus(500);
     }
 
     /**

+ 31 - 53
tests/TestCase/Error/Middleware/ErrorHandlerMiddlewareTest.php

@@ -24,6 +24,7 @@ use Cake\TestSuite\TestCase;
 use Error;
 use LogicException;
 use Psr\Log\LoggerInterface;
+use TestApp\Http\TestRequestHandler;
 
 /**
  * Test for ErrorHandlerMiddleware
@@ -71,14 +72,10 @@ class ErrorHandlerMiddlewareTest extends TestCase
         $this->logger->expects($this->never())->method('log');
 
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
 
         $middleware = new ErrorHandlerMiddleware();
-        $next = function ($req, $res) {
-            return $res;
-        };
-        $result = $middleware($request, $response, $next);
-        $this->assertSame($result, $response);
+        $result = $middleware->process($request, new TestRequestHandler());
+        $this->assertInstanceOf(Response::class, $result);
     }
 
     /**
@@ -90,13 +87,12 @@ class ErrorHandlerMiddlewareTest extends TestCase
         $this->expectException(\Exception::class);
         $this->expectExceptionMessage('The \'TotallyInvalid\' renderer class could not be found');
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
 
         $middleware = new ErrorHandlerMiddleware('TotallyInvalid');
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new \Exception('Something bad');
-        };
-        $middleware($request, $response, $next);
+        });
+        $middleware->process($request, $handler);
     }
 
     /**
@@ -107,7 +103,6 @@ class ErrorHandlerMiddlewareTest extends TestCase
     public function testRendererFactory()
     {
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
 
         $factory = function ($exception) {
             $this->assertInstanceOf('LogicException', $exception);
@@ -122,10 +117,10 @@ class ErrorHandlerMiddlewareTest extends TestCase
             return $mock;
         };
         $middleware = new ErrorHandlerMiddleware($factory);
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new LogicException('Something bad');
-        };
-        $middleware($request, $response, $next);
+        });
+        $middleware->process($request, $handler);
     }
 
     /**
@@ -136,15 +131,12 @@ class ErrorHandlerMiddlewareTest extends TestCase
     public function testHandleException()
     {
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
         $middleware = new ErrorHandlerMiddleware();
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new \Cake\Http\Exception\NotFoundException('whoops');
-        };
-        $result = $middleware($request, $response, $next);
-        $this->assertInstanceOf('Psr\Http\Message\ResponseInterface', $result);
+        });
+        $result = $middleware->process($request, $handler);
         $this->assertInstanceOf('Cake\Http\Response', $result);
-        $this->assertNotSame($result, $response);
         $this->assertEquals(404, $result->getStatusCode());
         $this->assertContains('was not found', '' . $result->getBody());
     }
@@ -159,14 +151,12 @@ class ErrorHandlerMiddlewareTest extends TestCase
         $request = ServerRequestFactory::fromGlobals();
         $request = $request->withHeader('Accept', 'application/json');
 
-        $response = new Response();
         $middleware = new ErrorHandlerMiddleware();
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new \Cake\Http\Exception\NotFoundException('whoops');
-        };
-        $result = $middleware($request, $response, $next);
+        });
+        $result = $middleware->process($request, $handler);
         $this->assertInstanceOf('Cake\Http\Response', $result);
-        $this->assertNotSame($result, $response);
         $this->assertEquals(404, $result->getStatusCode());
         $this->assertContains('"message": "whoops"', '' . $result->getBody());
         $this->assertEquals('application/json; charset=UTF-8', $result->getHeaderLine('Content-type'));
@@ -179,14 +169,11 @@ class ErrorHandlerMiddlewareTest extends TestCase
      */
     public function testHandlePHP7Error()
     {
-        $this->skipIf(version_compare(PHP_VERSION, '7.0.0', '<'), 'Error class only exists since PHP 7.');
-
         $middleware = new ErrorHandlerMiddleware();
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
         $error = new Error();
 
-        $result = $middleware->handleException($error, $request, $response);
+        $result = $middleware->handleException($error, $request);
         $this->assertInstanceOf(Response::class, $result);
     }
 
@@ -213,13 +200,11 @@ class ErrorHandlerMiddlewareTest extends TestCase
             'REQUEST_URI' => '/target/url',
             'HTTP_REFERER' => '/other/path',
         ]);
-        $response = new Response();
         $middleware = new ErrorHandlerMiddleware(null, ['log' => true, 'trace' => true]);
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new \Cake\Http\Exception\NotFoundException('Kaboom!');
-        };
-        $result = $middleware($request, $response, $next);
-        $this->assertNotSame($result, $response);
+        });
+        $result = $middleware->process($request, $handler);
         $this->assertEquals(404, $result->getStatusCode());
         $this->assertContains('was not found', '' . $result->getBody());
     }
@@ -245,14 +230,12 @@ class ErrorHandlerMiddlewareTest extends TestCase
             'REQUEST_URI' => '/target/url',
             'HTTP_REFERER' => '/other/path',
         ]);
-        $response = new Response();
         $middleware = new ErrorHandlerMiddleware(null, ['log' => true, 'trace' => true]);
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             $previous = new \Cake\Datasource\Exception\RecordNotFoundException('Previous logged');
             throw new \Cake\Http\Exception\NotFoundException('Kaboom!', null, $previous);
-        };
-        $result = $middleware($request, $response, $next);
-        $this->assertNotSame($result, $response);
+        });
+        $result = $middleware->process($request, $handler);
         $this->assertEquals(404, $result->getStatusCode());
         $this->assertContains('was not found', '' . $result->getBody());
     }
@@ -267,16 +250,14 @@ class ErrorHandlerMiddlewareTest extends TestCase
         $this->logger->expects($this->never())->method('log');
 
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
         $middleware = new ErrorHandlerMiddleware(null, [
             'log' => true,
             'skipLog' => ['Cake\Http\Exception\NotFoundException'],
         ]);
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new \Cake\Http\Exception\NotFoundException('Kaboom!');
-        };
-        $result = $middleware($request, $response, $next);
-        $this->assertNotSame($result, $response);
+        });
+        $result = $middleware->process($request, $handler);
         $this->assertEquals(404, $result->getStatusCode());
         $this->assertContains('was not found', '' . $result->getBody());
     }
@@ -301,13 +282,11 @@ class ErrorHandlerMiddlewareTest extends TestCase
             ));
 
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
         $middleware = new ErrorHandlerMiddleware(null, ['log' => true]);
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new \Cake\Routing\Exception\MissingControllerException(['class' => 'Articles']);
-        };
-        $result = $middleware($request, $response, $next);
-        $this->assertNotSame($result, $response);
+        });
+        $result = $middleware->process($request, $handler);
         $this->assertEquals(404, $result->getStatusCode());
     }
 
@@ -319,7 +298,6 @@ class ErrorHandlerMiddlewareTest extends TestCase
     public function testHandleExceptionRenderingFails()
     {
         $request = ServerRequestFactory::fromGlobals();
-        $response = new Response();
 
         $factory = function ($exception) {
             $mock = $this->getMockBuilder(ExceptionRendererInterface::class)
@@ -332,10 +310,10 @@ class ErrorHandlerMiddlewareTest extends TestCase
             return $mock;
         };
         $middleware = new ErrorHandlerMiddleware($factory);
-        $next = function ($req, $res) {
+        $handler = new TestRequestHandler(function ($req) {
             throw new \Cake\Http\Exception\ServiceUnavailableException('whoops');
-        };
-        $response = $middleware($request, $response, $next);
+        });
+        $response = $middleware->process($request, $handler);
         $this->assertEquals(500, $response->getStatusCode());
         $this->assertEquals('An Internal Server Error Occurred', '' . $response->getBody());
     }