diff --git a/src/Middleware/ErrorHandler.php b/src/Middleware/ErrorHandler.php
index 7588733..853bf57 100644
--- a/src/Middleware/ErrorHandler.php
+++ b/src/Middleware/ErrorHandler.php
@@ -23,178 +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 ErrorHandlerMiddleware
{
- /**
- * @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/ErrorHandlerMiddleware.php b/src/Middleware/ErrorHandlerMiddleware.php
new file mode 100644
index 0000000..0eb0f9b
--- /dev/null
+++ b/src/Middleware/ErrorHandlerMiddleware.php
@@ -0,0 +1,202 @@
+
+ * 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.
+ *
+ * @todo Mark this error middleware as final in v4
+ */
+/* final */ class ErrorHandlerMiddleware 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/ErrorHandlerTest.php b/test/Middleware/ErrorHandlerMiddlewareTest.php
similarity index 93%
rename from test/Middleware/ErrorHandlerTest.php
rename to test/Middleware/ErrorHandlerMiddlewareTest.php
index 8900584..c689694 100644
--- a/test/Middleware/ErrorHandlerTest.php
+++ b/test/Middleware/ErrorHandlerMiddlewareTest.php
@@ -18,7 +18,7 @@
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;
use Zend\Escaper\Escaper;
-use Zend\Stratigility\Middleware\ErrorHandler;
+use Zend\Stratigility\Middleware\ErrorHandlerMiddleware;
use Zend\Stratigility\Middleware\ErrorResponseGenerator;
use function error_reporting;
@@ -26,7 +26,7 @@
use const E_USER_DEPRECATED;
-class ErrorHandlerTest extends TestCase
+class ErrorHandlerMiddlewareTest extends TestCase
{
/** @var ResponseInterface|ObjectProphecy */
private $response;
@@ -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);
@@ -54,7 +74,7 @@ public function tearDown()
public function createMiddleware($isDevelopmentMode = false)
{
$generator = new ErrorResponseGenerator($isDevelopmentMode);
- return new ErrorHandler($this->responseFactory, $generator);
+ return new ErrorHandlerMiddleware($this->responseFactory, $generator);
}
public function testReturnsResponseFromHandlerWhenNoProblemsOccur()
@@ -219,7 +239,7 @@ public function testCanProvideAlternateErrorResponseGenerator()
$this->response->getBody()->will([$this->body, 'reveal']);
$this->body->write('The client messed up')->shouldBeCalled();
- $middleware = new ErrorHandler($this->responseFactory, $generator);
+ $middleware = new ErrorHandlerMiddleware($this->responseFactory, $generator);
$result = $middleware->process($this->request->reveal(), $this->handler->reveal());
$this->assertSame($this->response->reveal(), $result);