From a523e3727fa22867b0c82e0d381edd602aaf82e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Mon, 19 Aug 2019 14:02:27 +0200
Subject: [PATCH 1/6] Added missing properties to `ErrorHandlerTest`
---
test/Middleware/ErrorHandlerTest.php | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/test/Middleware/ErrorHandlerTest.php b/test/Middleware/ErrorHandlerTest.php
index 8900584..ddf3015 100644
--- a/test/Middleware/ErrorHandlerTest.php
+++ b/test/Middleware/ErrorHandlerTest.php
@@ -34,6 +34,26 @@ class ErrorHandlerTest extends TestCase
/** @var callable */
private $responseFactory;
+ /**
+ * @var ObjectProphecy|ServerRequestInterface
+ */
+ private $request;
+
+ /**
+ * @var ObjectProphecy|StreamInterface
+ */
+ private $body;
+
+ /**
+ * @var ObjectProphecy|RequestHandlerInterface
+ */
+ private $handler;
+
+ /**
+ * @var int
+ */
+ private $errorReporting;
+
public function setUp()
{
$this->response = $this->prophesize(ResponseInterface::class);
From b5bfa34450190640a5c41296f1027e8bac302e6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Mon, 19 Aug 2019 14:04:37 +0200
Subject: [PATCH 2/6] Introducing `ErrorMiddleware`
The `ErrorMiddleware` is just a drop-in replacement for the `ErrorHandler` to solve a naming conflict.
As the `ErrorHandler` is implementing the `MiddlewareInterface`, it supposed to be called `ErrorMiddleware` instead.
---
src/Middleware/ErrorMiddleware.php | 200 ++++++++++++++++++
test/Middleware/ErrorMiddlewareTest.php | 259 ++++++++++++++++++++++++
2 files changed, 459 insertions(+)
create mode 100644 src/Middleware/ErrorMiddleware.php
create mode 100644 test/Middleware/ErrorMiddlewareTest.php
diff --git a/src/Middleware/ErrorMiddleware.php b/src/Middleware/ErrorMiddleware.php
new file mode 100644
index 0000000..a484c12
--- /dev/null
+++ b/src/Middleware/ErrorMiddleware.php
@@ -0,0 +1,200 @@
+
+ * function (
+ * Throwable $e,
+ * ServerRequestInterface $request,
+ * ResponseInterface $response
+ * ) : ResponseInterface
+ *
+ *
+ * These are provided the error, and the request responsible; the response
+ * provided is the response prototype provided to the ErrorHandler instance
+ * itself, and can be used as the basis for returning an error response.
+ *
+ * An error response generator must be provided as a constructor argument;
+ * if not provided, an instance of Zend\Stratigility\Middleware\ErrorResponseGenerator
+ * will be used.
+ *
+ * Listeners use the following signature:
+ *
+ *
+ * function (
+ * Throwable $e,
+ * ServerRequestInterface $request,
+ * ResponseInterface $response
+ * ) : void
+ *
+ *
+ * Listeners are given the error, the request responsible, and the generated
+ * error response, and can then react to them. They are best suited for
+ * logging and monitoring purposes.
+ *
+ * Listeners are attached using the attachListener() method, and triggered
+ * in the order attached.
+ */
+class ErrorMiddleware implements MiddlewareInterface
+{
+ /**
+ * @var callable[]
+ */
+ private $listeners = [];
+
+ /**
+ * @var callable Routine that will generate the error response.
+ */
+ private $responseGenerator;
+
+ /**
+ * @var callable
+ */
+ private $responseFactory;
+
+ /**
+ * @param callable $responseFactory A factory capable of returning an
+ * empty ResponseInterface instance to update and return when returning
+ * an error response.
+ * @param null|callable $responseGenerator Callback that will generate the final
+ * error response; if none is provided, ErrorResponseGenerator is used.
+ */
+ public function __construct(callable $responseFactory, callable $responseGenerator = null)
+ {
+ $this->responseFactory = function () use ($responseFactory) : ResponseInterface {
+ return $responseFactory();
+ };
+ $this->responseGenerator = $responseGenerator ?: new ErrorResponseGenerator();
+ }
+
+ /**
+ * Attach an error listener.
+ *
+ * Each listener receives the following three arguments:
+ *
+ * - Throwable $error
+ * - ServerRequestInterface $request
+ * - ResponseInterface $response
+ *
+ * These instances are all immutable, and the return values of
+ * listeners are ignored; use listeners for reporting purposes
+ * only.
+ */
+ public function attachListener(callable $listener) : void
+ {
+ if (in_array($listener, $this->listeners, true)) {
+ return;
+ }
+
+ $this->listeners[] = $listener;
+ }
+
+ /**
+ * Middleware to handle errors and exceptions in layers it wraps.
+ *
+ * Adds an error handler that will convert PHP errors to ErrorException
+ * instances.
+ *
+ * Internally, wraps the call to $next() in a try/catch block, catching
+ * all PHP Throwables.
+ *
+ * When an exception is caught, an appropriate error response is created
+ * and returned instead; otherwise, the response returned by $next is
+ * used.
+ */
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
+ {
+ set_error_handler($this->createErrorHandler());
+
+ try {
+ $response = $handler->handle($request);
+ } catch (Throwable $e) {
+ $response = $this->handleThrowable($e, $request);
+ }
+
+ restore_error_handler();
+
+ return $response;
+ }
+
+ /**
+ * Handles all throwables, generating and returning a response.
+ *
+ * Passes the error, request, and response prototype to createErrorResponse(),
+ * triggers all listeners with the same arguments (but using the response
+ * returned from createErrorResponse()), and then returns the response.
+ */
+ private function handleThrowable(Throwable $e, ServerRequestInterface $request) : ResponseInterface
+ {
+ $generator = $this->responseGenerator;
+ $response = $generator($e, $request, ($this->responseFactory)());
+ $this->triggerListeners($e, $request, $response);
+ return $response;
+ }
+
+ /**
+ * Creates and returns a callable error handler that raises exceptions.
+ *
+ * Only raises exceptions for errors that are within the error_reporting mask.
+ */
+ private function createErrorHandler() : callable
+ {
+ /**
+ * @throws ErrorException if error is not within the error_reporting mask.
+ */
+ return function (int $errno, string $errstr, string $errfile, int $errline) : void {
+ if (! (error_reporting() & $errno)) {
+ // error_reporting does not include this error
+ return;
+ }
+
+ throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
+ };
+ }
+
+ /**
+ * Trigger all error listeners.
+ */
+ private function triggerListeners(
+ Throwable $error,
+ ServerRequestInterface $request,
+ ResponseInterface $response
+ ) : void {
+ foreach ($this->listeners as $listener) {
+ $listener($error, $request, $response);
+ }
+ }
+}
diff --git a/test/Middleware/ErrorMiddlewareTest.php b/test/Middleware/ErrorMiddlewareTest.php
new file mode 100644
index 0000000..552b4a2
--- /dev/null
+++ b/test/Middleware/ErrorMiddlewareTest.php
@@ -0,0 +1,259 @@
+response = $this->prophesize(ResponseInterface::class);
+ $this->responseFactory = function () {
+ return $this->response->reveal();
+ };
+ $this->request = $this->prophesize(ServerRequestInterface::class);
+ $this->body = $this->prophesize(StreamInterface::class);
+ $this->handler = $this->prophesize(RequestHandlerInterface::class);
+ $this->errorReporting = error_reporting();
+ }
+
+ public function tearDown()
+ {
+ error_reporting($this->errorReporting);
+ }
+
+ public function createMiddleware($isDevelopmentMode = false)
+ {
+ $generator = new ErrorResponseGenerator($isDevelopmentMode);
+ return new ErrorMiddleware($this->responseFactory, $generator);
+ }
+
+ public function testReturnsResponseFromHandlerWhenNoProblemsOccur()
+ {
+ $expectedResponse = $this->prophesize(ResponseInterface::class)->reveal();
+
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->willReturn($expectedResponse);
+
+ $this->response->withStatus(Argument::any())->shouldNotBeCalled();
+
+ $middleware = $this->createMiddleware();
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($expectedResponse, $result);
+ }
+
+ public function testReturnsErrorResponseIfHandlerDoesNotReturnAResponse()
+ {
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->willReturn(null);
+
+ $this->body->write('Unknown Error')->shouldBeCalled();
+ $this->response->getStatusCode()->willReturn(200);
+ $this->response->withStatus(500)->will([$this->response, 'reveal']);
+ $this->response->getReasonPhrase()->willReturn('');
+ $this->response->getBody()->will([$this->body, 'reveal']);
+
+ $middleware = $this->createMiddleware();
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($this->response->reveal(), $result);
+ }
+
+ public function testReturnsErrorResponseIfHandlerRaisesAnErrorInTheErrorMask()
+ {
+ error_reporting(E_USER_DEPRECATED);
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->will(function () {
+ trigger_error('Deprecated', E_USER_DEPRECATED);
+ });
+
+ $this->body->write('Unknown Error')->shouldBeCalled();
+ $this->response->getStatusCode()->willReturn(200);
+ $this->response->withStatus(500)->will([$this->response, 'reveal']);
+ $this->response->getReasonPhrase()->willReturn('');
+ $this->response->getBody()->will([$this->body, 'reveal']);
+
+ $middleware = $this->createMiddleware();
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($this->response->reveal(), $result);
+ }
+
+ public function testReturnsResponseFromHandlerWhenErrorRaisedIsNotInTheErrorMask()
+ {
+ $originalMask = error_reporting();
+ error_reporting($originalMask & ~E_USER_DEPRECATED);
+
+ $expectedResponse = $this->prophesize(ResponseInterface::class)->reveal();
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->will(function () use ($expectedResponse) {
+ trigger_error('Deprecated', E_USER_DEPRECATED);
+ return $expectedResponse;
+ });
+
+ $this->body->write('Unknown Error')->shouldNotBeCalled();
+ $this->response->getStatusCode()->shouldNotBeCalled();
+ $this->response->withStatus(Argument::any())->shouldNotBeCalled();
+
+ $middleware = $this->createMiddleware();
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($expectedResponse, $result);
+ }
+
+ public function testReturnsErrorResponseIfHandlerRaisesAnException()
+ {
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->willThrow(new RuntimeException('Exception raised', 503));
+
+ $this->body->write('Unknown Error')->shouldBeCalled();
+ $this->response->getStatusCode()->willReturn(200);
+ $this->response->withStatus(503)->will([$this->response, 'reveal']);
+ $this->response->getReasonPhrase()->willReturn('');
+ $this->response->getBody()->will([$this->body, 'reveal']);
+
+ $middleware = $this->createMiddleware();
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($this->response->reveal(), $result);
+ }
+
+ public function testResponseErrorMessageIncludesStackTraceIfDevelopmentModeIsEnabled()
+ {
+ $exception = new RuntimeException('Exception raised', 503);
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->willThrow($exception);
+
+ $this->body
+ ->write((new Escaper())
+ ->escapeHtml((string) $exception))->shouldBeCalled();
+ $this->response->getStatusCode()->willReturn(200);
+ $this->response->withStatus(503)->will([$this->response, 'reveal']);
+ $this->response->getReasonPhrase()->willReturn('');
+ $this->response->getBody()->will([$this->body, 'reveal']);
+
+ $middleware = $this->createMiddleware(true);
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($this->response->reveal(), $result);
+ }
+
+ public function testErrorHandlingTriggersListeners()
+ {
+ $exception = new RuntimeException('Exception raised', 503);
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->willThrow($exception);
+
+ $this->body->write('Unknown Error')->shouldBeCalled();
+ $this->response->getStatusCode()->willReturn(200);
+ $this->response->withStatus(503)->will([$this->response, 'reveal']);
+ $this->response->getReasonPhrase()->willReturn('');
+ $this->response->getBody()->will([$this->body, 'reveal']);
+
+ $listener = function ($error, $request, $response) use ($exception) {
+ $this->assertSame($exception, $error, 'Listener did not receive same exception as was raised');
+ $this->assertSame($this->request->reveal(), $request, 'Listener did not receive same request');
+ $this->assertSame($this->response->reveal(), $response, 'Listener did not receive same response');
+ };
+ $listener2 = clone $listener;
+
+ $middleware = $this->createMiddleware();
+ $middleware->attachListener($listener);
+ $middleware->attachListener($listener2);
+
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($this->response->reveal(), $result);
+ }
+
+ public function testCanProvideAlternateErrorResponseGenerator()
+ {
+ $generator = function ($e, $request, $response) {
+ $response = $response->withStatus(400);
+ $response->getBody()->write('The client messed up');
+ return $response;
+ };
+
+ $this->handler
+ ->handle(Argument::type(ServerRequestInterface::class))
+ ->willThrow(new RuntimeException('Exception raised', 503));
+
+ $this->response->withStatus(400)->will([$this->response, 'reveal']);
+ $this->response->getBody()->will([$this->body, 'reveal']);
+ $this->body->write('The client messed up')->shouldBeCalled();
+
+ $middleware = new ErrorMiddleware($this->responseFactory, $generator);
+ $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
+
+ $this->assertSame($this->response->reveal(), $result);
+ }
+
+ public function testTheSameListenerIsAttachedOnlyOnce()
+ {
+ $middleware = $this->createMiddleware();
+ $listener = function () {
+ };
+
+ $middleware->attachListener($listener);
+ $middleware->attachListener($listener);
+
+ self::assertAttributeCount(1, 'listeners', $middleware);
+ }
+}
From aaed976d9bae8360f1769ff5c202a71cd76f6fdb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Mon, 19 Aug 2019 14:05:14 +0200
Subject: [PATCH 3/6] Marking `ErrorHandler` deprecated
The `ErrorHandler` should be removed in v4.
---
src/Middleware/ErrorHandler.php | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Middleware/ErrorHandler.php b/src/Middleware/ErrorHandler.php
index 7588733..a959f3d 100644
--- a/src/Middleware/ErrorHandler.php
+++ b/src/Middleware/ErrorHandler.php
@@ -67,6 +67,8 @@
*
* Listeners are attached using the attachListener() method, and triggered
* in the order attached.
+ *
+ * @deprecated This class is being dropped in v4.0 in favor of the ErrorMiddleware.
*/
class ErrorHandler implements MiddlewareInterface
{
From b1b6acfb92eea9149f7b17ffb051fb145e6989c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Mon, 19 Aug 2019 14:07:30 +0200
Subject: [PATCH 4/6] `ErrorHandler` extends the `ErrorMiddleware`
By just extending the `ErrorMiddleware`, we can remove the dedicated unit test and the duplicated code for the `ErrorHandler`
---
src/Middleware/ErrorHandler.php | 174 +-----------------
src/Middleware/ErrorMiddleware.php | 4 +-
test/Middleware/ErrorHandlerTest.php | 259 ---------------------------
3 files changed, 4 insertions(+), 433 deletions(-)
delete mode 100644 test/Middleware/ErrorHandlerTest.php
diff --git a/src/Middleware/ErrorHandler.php b/src/Middleware/ErrorHandler.php
index a959f3d..e52001f 100644
--- a/src/Middleware/ErrorHandler.php
+++ b/src/Middleware/ErrorHandler.php
@@ -23,180 +23,8 @@
use function set_error_handler;
/**
- * Error handler middleware.
- *
- * Use this middleware as the outermost (or close to outermost) middleware
- * layer, and use it to intercept PHP errors and exceptions.
- *
- * The class offers two extension points:
- *
- * - Error response generators.
- * - Listeners.
- *
- * Error response generators are callables with the following signature:
- *
- *
- * function (
- * Throwable $e,
- * ServerRequestInterface $request,
- * ResponseInterface $response
- * ) : ResponseInterface
- *
- *
- * These are provided the error, and the request responsible; the response
- * provided is the response prototype provided to the ErrorHandler instance
- * itself, and can be used as the basis for returning an error response.
- *
- * An error response generator must be provided as a constructor argument;
- * if not provided, an instance of Zend\Stratigility\Middleware\ErrorResponseGenerator
- * will be used.
- *
- * Listeners use the following signature:
- *
- *
- * function (
- * Throwable $e,
- * ServerRequestInterface $request,
- * ResponseInterface $response
- * ) : void
- *
- *
- * Listeners are given the error, the request responsible, and the generated
- * error response, and can then react to them. They are best suited for
- * logging and monitoring purposes.
- *
- * Listeners are attached using the attachListener() method, and triggered
- * in the order attached.
- *
* @deprecated This class is being dropped in v4.0 in favor of the ErrorMiddleware.
*/
-class ErrorHandler implements MiddlewareInterface
+class ErrorHandler extends ErrorMiddleware
{
- /**
- * @var callable[]
- */
- private $listeners = [];
-
- /**
- * @var callable Routine that will generate the error response.
- */
- private $responseGenerator;
-
- /**
- * @var callable
- */
- private $responseFactory;
-
- /**
- * @param callable $responseFactory A factory capable of returning an
- * empty ResponseInterface instance to update and return when returning
- * an error response.
- * @param null|callable $responseGenerator Callback that will generate the final
- * error response; if none is provided, ErrorResponseGenerator is used.
- */
- public function __construct(callable $responseFactory, callable $responseGenerator = null)
- {
- $this->responseFactory = function () use ($responseFactory) : ResponseInterface {
- return $responseFactory();
- };
- $this->responseGenerator = $responseGenerator ?: new ErrorResponseGenerator();
- }
-
- /**
- * Attach an error listener.
- *
- * Each listener receives the following three arguments:
- *
- * - Throwable $error
- * - ServerRequestInterface $request
- * - ResponseInterface $response
- *
- * These instances are all immutable, and the return values of
- * listeners are ignored; use listeners for reporting purposes
- * only.
- */
- public function attachListener(callable $listener) : void
- {
- if (in_array($listener, $this->listeners, true)) {
- return;
- }
-
- $this->listeners[] = $listener;
- }
-
- /**
- * Middleware to handle errors and exceptions in layers it wraps.
- *
- * Adds an error handler that will convert PHP errors to ErrorException
- * instances.
- *
- * Internally, wraps the call to $next() in a try/catch block, catching
- * all PHP Throwables.
- *
- * When an exception is caught, an appropriate error response is created
- * and returned instead; otherwise, the response returned by $next is
- * used.
- */
- public function process(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
- {
- set_error_handler($this->createErrorHandler());
-
- try {
- $response = $handler->handle($request);
- } catch (Throwable $e) {
- $response = $this->handleThrowable($e, $request);
- }
-
- restore_error_handler();
-
- return $response;
- }
-
- /**
- * Handles all throwables, generating and returning a response.
- *
- * Passes the error, request, and response prototype to createErrorResponse(),
- * triggers all listeners with the same arguments (but using the response
- * returned from createErrorResponse()), and then returns the response.
- */
- private function handleThrowable(Throwable $e, ServerRequestInterface $request) : ResponseInterface
- {
- $generator = $this->responseGenerator;
- $response = $generator($e, $request, ($this->responseFactory)());
- $this->triggerListeners($e, $request, $response);
- return $response;
- }
-
- /**
- * Creates and returns a callable error handler that raises exceptions.
- *
- * Only raises exceptions for errors that are within the error_reporting mask.
- */
- private function createErrorHandler() : callable
- {
- /**
- * @throws ErrorException if error is not within the error_reporting mask.
- */
- return function (int $errno, string $errstr, string $errfile, int $errline) : void {
- if (! (error_reporting() & $errno)) {
- // error_reporting does not include this error
- return;
- }
-
- throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
- };
- }
-
- /**
- * Trigger all error listeners.
- */
- private function triggerListeners(
- Throwable $error,
- ServerRequestInterface $request,
- ResponseInterface $response
- ) : void {
- foreach ($this->listeners as $listener) {
- $listener($error, $request, $response);
- }
- }
}
diff --git a/src/Middleware/ErrorMiddleware.php b/src/Middleware/ErrorMiddleware.php
index a484c12..a2d7107 100644
--- a/src/Middleware/ErrorMiddleware.php
+++ b/src/Middleware/ErrorMiddleware.php
@@ -67,8 +67,10 @@
*
* Listeners are attached using the attachListener() method, and triggered
* in the order attached.
+ *
+ * @todo Mark this error middleware as final in v4
*/
-class ErrorMiddleware implements MiddlewareInterface
+/* final */ class ErrorMiddleware implements MiddlewareInterface
{
/**
* @var callable[]
diff --git a/test/Middleware/ErrorHandlerTest.php b/test/Middleware/ErrorHandlerTest.php
deleted file mode 100644
index ddf3015..0000000
--- a/test/Middleware/ErrorHandlerTest.php
+++ /dev/null
@@ -1,259 +0,0 @@
-response = $this->prophesize(ResponseInterface::class);
- $this->responseFactory = function () {
- return $this->response->reveal();
- };
- $this->request = $this->prophesize(ServerRequestInterface::class);
- $this->body = $this->prophesize(StreamInterface::class);
- $this->handler = $this->prophesize(RequestHandlerInterface::class);
- $this->errorReporting = error_reporting();
- }
-
- public function tearDown()
- {
- error_reporting($this->errorReporting);
- }
-
- public function createMiddleware($isDevelopmentMode = false)
- {
- $generator = new ErrorResponseGenerator($isDevelopmentMode);
- return new ErrorHandler($this->responseFactory, $generator);
- }
-
- public function testReturnsResponseFromHandlerWhenNoProblemsOccur()
- {
- $expectedResponse = $this->prophesize(ResponseInterface::class)->reveal();
-
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->willReturn($expectedResponse);
-
- $this->response->withStatus(Argument::any())->shouldNotBeCalled();
-
- $middleware = $this->createMiddleware();
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($expectedResponse, $result);
- }
-
- public function testReturnsErrorResponseIfHandlerDoesNotReturnAResponse()
- {
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->willReturn(null);
-
- $this->body->write('Unknown Error')->shouldBeCalled();
- $this->response->getStatusCode()->willReturn(200);
- $this->response->withStatus(500)->will([$this->response, 'reveal']);
- $this->response->getReasonPhrase()->willReturn('');
- $this->response->getBody()->will([$this->body, 'reveal']);
-
- $middleware = $this->createMiddleware();
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($this->response->reveal(), $result);
- }
-
- public function testReturnsErrorResponseIfHandlerRaisesAnErrorInTheErrorMask()
- {
- error_reporting(E_USER_DEPRECATED);
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->will(function () {
- trigger_error('Deprecated', E_USER_DEPRECATED);
- });
-
- $this->body->write('Unknown Error')->shouldBeCalled();
- $this->response->getStatusCode()->willReturn(200);
- $this->response->withStatus(500)->will([$this->response, 'reveal']);
- $this->response->getReasonPhrase()->willReturn('');
- $this->response->getBody()->will([$this->body, 'reveal']);
-
- $middleware = $this->createMiddleware();
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($this->response->reveal(), $result);
- }
-
- public function testReturnsResponseFromHandlerWhenErrorRaisedIsNotInTheErrorMask()
- {
- $originalMask = error_reporting();
- error_reporting($originalMask & ~E_USER_DEPRECATED);
-
- $expectedResponse = $this->prophesize(ResponseInterface::class)->reveal();
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->will(function () use ($expectedResponse) {
- trigger_error('Deprecated', E_USER_DEPRECATED);
- return $expectedResponse;
- });
-
- $this->body->write('Unknown Error')->shouldNotBeCalled();
- $this->response->getStatusCode()->shouldNotBeCalled();
- $this->response->withStatus(Argument::any())->shouldNotBeCalled();
-
- $middleware = $this->createMiddleware();
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($expectedResponse, $result);
- }
-
- public function testReturnsErrorResponseIfHandlerRaisesAnException()
- {
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->willThrow(new RuntimeException('Exception raised', 503));
-
- $this->body->write('Unknown Error')->shouldBeCalled();
- $this->response->getStatusCode()->willReturn(200);
- $this->response->withStatus(503)->will([$this->response, 'reveal']);
- $this->response->getReasonPhrase()->willReturn('');
- $this->response->getBody()->will([$this->body, 'reveal']);
-
- $middleware = $this->createMiddleware();
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($this->response->reveal(), $result);
- }
-
- public function testResponseErrorMessageIncludesStackTraceIfDevelopmentModeIsEnabled()
- {
- $exception = new RuntimeException('Exception raised', 503);
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->willThrow($exception);
-
- $this->body
- ->write((new Escaper())
- ->escapeHtml((string) $exception))->shouldBeCalled();
- $this->response->getStatusCode()->willReturn(200);
- $this->response->withStatus(503)->will([$this->response, 'reveal']);
- $this->response->getReasonPhrase()->willReturn('');
- $this->response->getBody()->will([$this->body, 'reveal']);
-
- $middleware = $this->createMiddleware(true);
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($this->response->reveal(), $result);
- }
-
- public function testErrorHandlingTriggersListeners()
- {
- $exception = new RuntimeException('Exception raised', 503);
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->willThrow($exception);
-
- $this->body->write('Unknown Error')->shouldBeCalled();
- $this->response->getStatusCode()->willReturn(200);
- $this->response->withStatus(503)->will([$this->response, 'reveal']);
- $this->response->getReasonPhrase()->willReturn('');
- $this->response->getBody()->will([$this->body, 'reveal']);
-
- $listener = function ($error, $request, $response) use ($exception) {
- $this->assertSame($exception, $error, 'Listener did not receive same exception as was raised');
- $this->assertSame($this->request->reveal(), $request, 'Listener did not receive same request');
- $this->assertSame($this->response->reveal(), $response, 'Listener did not receive same response');
- };
- $listener2 = clone $listener;
-
- $middleware = $this->createMiddleware();
- $middleware->attachListener($listener);
- $middleware->attachListener($listener2);
-
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($this->response->reveal(), $result);
- }
-
- public function testCanProvideAlternateErrorResponseGenerator()
- {
- $generator = function ($e, $request, $response) {
- $response = $response->withStatus(400);
- $response->getBody()->write('The client messed up');
- return $response;
- };
-
- $this->handler
- ->handle(Argument::type(ServerRequestInterface::class))
- ->willThrow(new RuntimeException('Exception raised', 503));
-
- $this->response->withStatus(400)->will([$this->response, 'reveal']);
- $this->response->getBody()->will([$this->body, 'reveal']);
- $this->body->write('The client messed up')->shouldBeCalled();
-
- $middleware = new ErrorHandler($this->responseFactory, $generator);
- $result = $middleware->process($this->request->reveal(), $this->handler->reveal());
-
- $this->assertSame($this->response->reveal(), $result);
- }
-
- public function testTheSameListenerIsAttachedOnlyOnce()
- {
- $middleware = $this->createMiddleware();
- $listener = function () {
- };
-
- $middleware->attachListener($listener);
- $middleware->attachListener($listener);
-
- self::assertAttributeCount(1, 'listeners', $middleware);
- }
-}
From cf7793d9f5cabcda56d13b1442d988c00930eced Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Mon, 19 Aug 2019 14:15:31 +0200
Subject: [PATCH 5/6] Renaming `ErrorMiddleware` to `ErrorHandlerMiddleware`
Actually, its an error handling middleware.
Renaming to `ErrorHandlerMiddleware` is more beneficial as just `ErrorMiddleware`.
---
src/Middleware/ErrorHandler.php | 2 +-
.../{ErrorMiddleware.php => ErrorHandlerMiddleware.php} | 2 +-
test/Middleware/ErrorMiddlewareTest.php | 6 +++---
3 files changed, 5 insertions(+), 5 deletions(-)
rename src/Middleware/{ErrorMiddleware.php => ErrorHandlerMiddleware.php} (98%)
diff --git a/src/Middleware/ErrorHandler.php b/src/Middleware/ErrorHandler.php
index e52001f..853bf57 100644
--- a/src/Middleware/ErrorHandler.php
+++ b/src/Middleware/ErrorHandler.php
@@ -25,6 +25,6 @@
/**
* @deprecated This class is being dropped in v4.0 in favor of the ErrorMiddleware.
*/
-class ErrorHandler extends ErrorMiddleware
+class ErrorHandler extends ErrorHandlerMiddleware
{
}
diff --git a/src/Middleware/ErrorMiddleware.php b/src/Middleware/ErrorHandlerMiddleware.php
similarity index 98%
rename from src/Middleware/ErrorMiddleware.php
rename to src/Middleware/ErrorHandlerMiddleware.php
index a2d7107..0eb0f9b 100644
--- a/src/Middleware/ErrorMiddleware.php
+++ b/src/Middleware/ErrorHandlerMiddleware.php
@@ -70,7 +70,7 @@
*
* @todo Mark this error middleware as final in v4
*/
-/* final */ class ErrorMiddleware implements MiddlewareInterface
+/* final */ class ErrorHandlerMiddleware implements MiddlewareInterface
{
/**
* @var callable[]
diff --git a/test/Middleware/ErrorMiddlewareTest.php b/test/Middleware/ErrorMiddlewareTest.php
index 552b4a2..cfa075a 100644
--- a/test/Middleware/ErrorMiddlewareTest.php
+++ b/test/Middleware/ErrorMiddlewareTest.php
@@ -18,7 +18,7 @@
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;
use Zend\Escaper\Escaper;
-use Zend\Stratigility\Middleware\ErrorMiddleware;
+use Zend\Stratigility\Middleware\ErrorHandlerMiddleware;
use Zend\Stratigility\Middleware\ErrorResponseGenerator;
use function error_reporting;
@@ -74,7 +74,7 @@ public function tearDown()
public function createMiddleware($isDevelopmentMode = false)
{
$generator = new ErrorResponseGenerator($isDevelopmentMode);
- return new ErrorMiddleware($this->responseFactory, $generator);
+ return new ErrorHandlerMiddleware($this->responseFactory, $generator);
}
public function testReturnsResponseFromHandlerWhenNoProblemsOccur()
@@ -239,7 +239,7 @@ public function testCanProvideAlternateErrorResponseGenerator()
$this->response->getBody()->will([$this->body, 'reveal']);
$this->body->write('The client messed up')->shouldBeCalled();
- $middleware = new ErrorMiddleware($this->responseFactory, $generator);
+ $middleware = new ErrorHandlerMiddleware($this->responseFactory, $generator);
$result = $middleware->process($this->request->reveal(), $this->handler->reveal());
$this->assertSame($this->response->reveal(), $result);
From 46f69fe17df25e8f1f5222b6deb025b6ec2ce59f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maximilian=20B=C3=B6sing?=
<2189546+boesing@users.noreply.github.com>
Date: Mon, 19 Aug 2019 14:17:37 +0200
Subject: [PATCH 6/6] Renaming the `ErrorMiddlewareTest` to
`ErrorHandlerMiddlewareTest`
---
.../{ErrorMiddlewareTest.php => ErrorHandlerMiddlewareTest.php} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename test/Middleware/{ErrorMiddlewareTest.php => ErrorHandlerMiddlewareTest.php} (99%)
diff --git a/test/Middleware/ErrorMiddlewareTest.php b/test/Middleware/ErrorHandlerMiddlewareTest.php
similarity index 99%
rename from test/Middleware/ErrorMiddlewareTest.php
rename to test/Middleware/ErrorHandlerMiddlewareTest.php
index cfa075a..c689694 100644
--- a/test/Middleware/ErrorMiddlewareTest.php
+++ b/test/Middleware/ErrorHandlerMiddlewareTest.php
@@ -26,7 +26,7 @@
use const E_USER_DEPRECATED;
-class ErrorMiddlewareTest extends TestCase
+class ErrorHandlerMiddlewareTest extends TestCase
{
/** @var ResponseInterface|ObjectProphecy */
private $response;