From 29fed99ec0bd5d7d41b657c521f617b0c429e508 Mon Sep 17 00:00:00 2001 From: Sebastian Meyer Date: Fri, 12 Jul 2024 15:29:35 +0200 Subject: [PATCH] Update documentation for QueueRequestHandler --- .../guide/overview/queuerequesthandler.rst | 105 +++++++++ .phpdoc/guide/usage/usage.rst | 4 +- doc/classes/OCC-PSR15-AbstractMiddleware.html | 6 +- .../OCC-PSR15-QueueRequestHandler.html | 17 +- doc/files/src/AbstractMiddleware.php.txt | 2 - doc/files/src/QueueRequestHandler.php.txt | 15 +- doc/guides/overview/index.html | 13 ++ doc/guides/overview/queuerequesthandler.html | 214 ++++++++++++++++++ doc/guides/usage/usage.html | 4 +- src/AbstractMiddleware.php | 2 - src/QueueRequestHandler.php | 15 +- 11 files changed, 368 insertions(+), 29 deletions(-) diff --git a/.phpdoc/guide/overview/queuerequesthandler.rst b/.phpdoc/guide/overview/queuerequesthandler.rst index f354dc9..8b79587 100644 --- a/.phpdoc/guide/overview/queuerequesthandler.rst +++ b/.phpdoc/guide/overview/queuerequesthandler.rst @@ -3,3 +3,108 @@ QueueRequestHandler ################### +.. sidebar:: Table of Contents + .. contents:: + +The `QueueRequestHandler` is the core piece of this package. It fetches incoming HTTP requests, passes them through a +queue of middlewares and finally sends the response back to the client. It also catches any exceptions not handled by +a middleware and turns them into a proper HTTP error response. + +The `QueueRequestHandler` implements the +`Psr\Http\Server\RequestHandlerInterface `_ +following PHP-FIG's recommendation `PSR-15: HTTP Server Request Handlers `_. + +For a minimal working example have a look at :doc:`../usage/usage`. + +Properties +========== + +The `QueueRequestHandler` has three **read-only** properties. They are initially set at instantiation and can be +directly accessed from the object via magic methods (e.g. `$requestHandler->queue`). + +Middleware Queue +---------------- + +The queue of middlewares can be accessed as `QueueRequestHandler::queue` and offers a handy API to `enqueue()`, +`dequeue()` or otherwise manipulate its contents. All middlewares must implement `Psr\Http\Server\MiddlewareInterface`. +Have a look at :doc:`middlewarequeue` for more details. + +When instantiating a `QueueRequestHandler` the queue defaults to being empty. But you can optionally pass an iterable +set of middlewares to the constructor which are then put into the queue. To demonstrate, the following examples both +have exactly the same result. + + Examples: + + .. code-block:: php + use OCC\PSR15\QueueRequestHandler; + + $middlewares = [ + new MiddlewareOne(), + new MiddlewareTwo() + ]; + + $requestHandler = new QueueRequestHandler($middlewares); + + .. code-block:: php + use OCC\PSR15\QueueRequestHandler; + + $requestHandler = new QueueRequestHandler(); + + $requestHandler->queue->enqueue(new MiddlewareOne()); + $requestHandler->queue->enqueue(new MiddlewareTwo()); + + +HTTP Server Request +------------------- + +The server request is always available as `QueueRequestHandler::request`. It follows PHP-FIG's standard recommendation +`PSR-7: HTTP Message Interfaces `_ and implements the +`Psr\Http\Message\ServerRequestInterface `_. + +When instantiating a `QueueRequestHandler` the `$request` property is initially set by fetching the actual server +request data from superglobals. The property is reset each time the request is passed through a middleware and thus +always represents the current state of the request. + +HTTP Response +------------- + +The response can be read as `QueueRequestHandler::response`. It also follows PHP-FIG's standard recommendation +`PSR-7: HTTP Message Interfaces `_ and implements the +`Psr\Http\Message\ResponseInterface `_. + +When instantiating a `QueueRequestHandler` the `$response` property is initially set as a blank HTTP response with +status code `200`. The property is reset each time the response is passed through a middleware and thus +always represents the latest state of the response. + +Both, request and response, use the awesome implementations of `Guzzle `_. + +Methods +======= + +The `QueueRequestHandler` provides two public API methods, :php:method:`OCC\PSR15\QueueRequestHandler::handle()` and +:php:method:`OCC\PSR15\QueueRequestHandler::respond()`. As their names suggest, the former handles the server request +while the latter sends the response back to the client. Invoking the request handler object directly does the same as +calling the `handle()` method. + +Handling a Server Request +------------------------- + +After adding at least one middleware to the queue, you can start handling a request by simply calling +:php:method:`OCC\PSR15\QueueRequestHandler::handle()`. Optionally, you can pass a request object as argument, but since +the actual server request was already fetched in the constructor and will be used by default, most of the time you +don't need to. All request objects must implement `Psr\Http\Message\ServerRequestInterface`. + +The `handle()` method returns the final response after passing it through all middlewares. The response object always +implements `Psr\Http\Message\ResponseInterface`. + +In case of an error the request handler catches any exception and creates a response with the exception code as status +code (if it's within the valid range of HTTP status codes, otherwise it's set to `500 (Internal Server Error)`), and +the exception message as body. + +Sending the Response +-------------------- + +Sending the final response to the client is as easy as calling :php:method:`OCC\PSR15\QueueRequestHandler::respond()`. +Optionally, you can provide an exit code as argument (an integer in the range `0` to `254`). If you do so, script +execution is stopped after sending out the response and the given exit status is set. The status `0` means the request +was handled successfully, every other status is considered an error. diff --git a/.phpdoc/guide/usage/usage.rst b/.phpdoc/guide/usage/usage.rst index cb265ff..aedb075 100644 --- a/.phpdoc/guide/usage/usage.rst +++ b/.phpdoc/guide/usage/usage.rst @@ -20,7 +20,7 @@ The abstract middleware already implements a complete middleware, but it will ju anything. In order to have it do something, we need to implement our own :php:method:`OCC\PSR15\AbstractMiddleware::processRequest()` or :php:method:`OCC\PSR15\AbstractMiddleware::processResponse()` method, or both of them. -The logic here is the same as with every `PSR-15: HTTP Server Request Handler `_ +The logic here is the same as with every `PSR-15: HTTP Server Request Handlers `_ middleware: The request gets passed through all middlewares' `processRequest()` methods in order of their addition to the queue, then a response is created and passed through all `processResponse()` methods, **but in reverse order**! So the first middleware in the queue gets the request first, but the response last. @@ -149,7 +149,7 @@ Diving Deeper ============= To familiarize yourself with the FIFO principle of the middleware queue, you can try to exchange the two lines adding -the middlewares to the queue, i.e. adding `MiddlewareTwo` first and `MiddlewareOne` second. This will result in an HTTP +the middlewares to the queue, i.e. add `MiddlewareTwo` first and `MiddlewareOne` second. This will result in an HTTP response with status code `500 (Internal Server Error)`. This is exactly what we intended: Have a look at `MiddlewareTwo::processResponse()` again! If `$lastMiddlewarePassed` diff --git a/doc/classes/OCC-PSR15-AbstractMiddleware.html b/doc/classes/OCC-PSR15-AbstractMiddleware.html index 18e34d9..ca220e4 100644 --- a/doc/classes/OCC-PSR15-AbstractMiddleware.html +++ b/doc/classes/OCC-PSR15-AbstractMiddleware.html @@ -298,9 +298,9 @@

Allow the middleware to be invoked directly.

@@ -310,8 +310,6 @@ final __invoke(ServerRequestInterface $request, RequestHandlerInterface $handler) : ResponseInterface
-
APIYes
-
diff --git a/doc/classes/OCC-PSR15-QueueRequestHandler.html b/doc/classes/OCC-PSR15-QueueRequestHandler.html index 4868c66..08ce623 100644 --- a/doc/classes/OCC-PSR15-QueueRequestHandler.html +++ b/doc/classes/OCC-PSR15-QueueRequestHandler.html @@ -442,9 +442,9 @@

Create a queue-based PSR-15 HTTP Server Request Handler.

@@ -490,9 +490,9 @@

Allow the request handler to be invoked directly.

@@ -502,8 +502,6 @@ __invoke([ServerRequestInterface|null $request = null ]) : ResponseInterface
-
APIYes
-
@@ -606,9 +604,9 @@

Return the current response to the client.

@@ -630,7 +628,8 @@ : int|null = null
-

Exit code after sending out the response or NULL to continue

+

Exit status after sending out the response or NULL to continue

+

Must be in the range 0 to 254. The status 0 is used to terminate the program successfully.

diff --git a/doc/files/src/AbstractMiddleware.php.txt b/doc/files/src/AbstractMiddleware.php.txt index 6577645..451b1cd 100644 --- a/doc/files/src/AbstractMiddleware.php.txt +++ b/doc/files/src/AbstractMiddleware.php.txt @@ -99,8 +99,6 @@ abstract class AbstractMiddleware implements MiddlewareInterface * @param RequestHandler $handler The request handler to delegate to * * @return Response The response object - * - * @api */ final public function __invoke(ServerRequest $request, RequestHandler $handler): Response { diff --git a/doc/files/src/QueueRequestHandler.php.txt b/doc/files/src/QueueRequestHandler.php.txt index e29a280..5dab177 100644 --- a/doc/files/src/QueueRequestHandler.php.txt +++ b/doc/files/src/QueueRequestHandler.php.txt @@ -120,7 +120,6 @@ class QueueRequestHandler implements RequestHandler $exception->getMessage() ) ); - $this->respond(1); } } return $this->response; @@ -129,7 +128,9 @@ class QueueRequestHandler implements RequestHandler /** * Return the current response to the client. * - * @param ?int $exitCode Exit code after sending out the response or NULL to continue + * @param ?int $exitCode Exit status after sending out the response or NULL to continue + * + * Must be in the range 0 to 254. The status 0 is used to terminate the program successfully. * * @return void * @@ -166,6 +167,14 @@ class QueueRequestHandler implements RequestHandler } echo $this->response->getBody(); if (!is_null($exitCode)) { + $options = [ + 'options' => [ + 'default' => 1, + 'min_range' => 0, + 'max_range' => 254 + ] + ]; + $exitCode = filter_var($exitCode, FILTER_VALIDATE_INT, $options); exit($exitCode); } } @@ -226,8 +235,6 @@ class QueueRequestHandler implements RequestHandler * @param ?ServerRequest $request The PSR-7 server request to handle * * @return Response A PSR-7 compatible HTTP response - * - * @api */ public function __invoke(?ServerRequest $request = null): Response { diff --git a/doc/guides/overview/index.html b/doc/guides/overview/index.html index 4d904a4..b57b8ba 100644 --- a/doc/guides/overview/index.html +++ b/doc/guides/overview/index.html @@ -171,7 +171,20 @@ in other projects.

  • QueueRequestHandler +
  • diff --git a/doc/guides/overview/queuerequesthandler.html b/doc/guides/overview/queuerequesthandler.html index 8eee82c..a57fd83 100644 --- a/doc/guides/overview/queuerequesthandler.html +++ b/doc/guides/overview/queuerequesthandler.html @@ -153,6 +153,220 @@

    QueueRequestHandler

    +
    +
    +
    + +
    + +
    +
    + + +

    The QueueRequestHandler + is the core piece of this package. It fetches incoming HTTP requests, passes them through a +queue of middlewares and finally sends the response back to the client. It also catches any exceptions not handled by +a middleware and turns them into a proper HTTP error response.

    + + +

    The QueueRequestHandler + implements the +Psr\Http\Server\RequestHandlerInterface +following PHP-FIG's recommendation PSR-15: HTTP Server Request Handlers.

    + + +

    For a minimal working example have a look at Usage.

    + +
    +

    Properties

    + + +

    The QueueRequestHandler + has three read-only + properties. They are initially set at instantiation and can be +directly accessed from the object via magic methods (e.g. $requestHandler->queue +).

    + +
    +

    Middleware Queue

    + + +

    The queue of middlewares can be accessed as QueueRequestHandler::queue + and offers a handy API to enqueue() +, +dequeue() + or otherwise manipulate its contents. All middlewares must implement Psr\Http\Server\MiddlewareInterface +. +Have a look at MiddlewareQueue for more details.

    + + +

    When instantiating a QueueRequestHandler + the queue defaults to being empty. But you can optionally pass an iterable +set of middlewares to the constructor which are then put into the queue. To demonstrate, the following examples both +have exactly the same result.

    + +
    +

    Examples:

    +
    use OCC\PSR15\QueueRequestHandler;
    +
    +$middlewares = [
    +    new MiddlewareOne(),
    +    new MiddlewareTwo()
    +];
    +
    +$requestHandler = new QueueRequestHandler($middlewares);
    +
    use OCC\PSR15\QueueRequestHandler;
    +
    +$requestHandler = new QueueRequestHandler();
    +
    +$requestHandler->queue->enqueue(new MiddlewareOne());
    +$requestHandler->queue->enqueue(new MiddlewareTwo());
    +
    + +
    + +
    +

    HTTP Server Request

    + + +

    The server request is always available as QueueRequestHandler::request +. It follows PHP-FIG's standard recommendation +PSR-7: HTTP Message Interfaces and implements the +Psr\Http\Message\ServerRequestInterface.

    + + +

    When instantiating a QueueRequestHandler + the $request + property is initially set by fetching the actual server +request data from superglobals. The property is reset each time the request is passed through a middleware and thus +always represents the current state of the request.

    + +
    + +
    +

    HTTP Response

    + + +

    The response can be read as QueueRequestHandler::response +. It also follows PHP-FIG's standard recommendation +PSR-7: HTTP Message Interfaces and implements the +Psr\Http\Message\ResponseInterface.

    + + +

    When instantiating a QueueRequestHandler + the $response + property is initially set as a blank HTTP response with +status code 200 +. The property is reset each time the response is passed through a middleware and thus +always represents the latest state of the response.

    + + +

    Both, request and response, use the awesome implementations of Guzzle.

    + +
    + +
    + +
    +

    Methods

    + + +

    The QueueRequestHandler + provides two public API methods, QueueRequestHandler::handle() + and +QueueRequestHandler::respond() +. As their names suggest, the former handles the server request +while the latter sends the response back to the client. Invoking the request handler object directly does the same as +calling the handle() + method.

    + +
    +

    Handling a Server Request

    + + +

    After adding at least one middleware to the queue, you can start handling a request by simply calling +QueueRequestHandler::handle() +. Optionally, you can pass a request object as argument, but since +the actual server request was already fetched in the constructor and will be used by default, most of the time you +don't need to. All request objects must implement Psr\Http\Message\ServerRequestInterface +.

    + + +

    The handle() + method returns the final response after passing it through all middlewares. The response object always +implements Psr\Http\Message\ResponseInterface +.

    + + +

    In case of an error the request handler catches any exception and creates a response with the exception code as status +code (if it's within the valid range of HTTP status codes, otherwise it's set to 500 (Internal Server Error) +), and +the exception message as body.

    + +
    + +
    +

    Sending the Response

    + + +

    Sending the final response to the client is as easy as calling QueueRequestHandler::respond() +. +Optionally, you can provide an exit code as argument (an integer in the range 0 + to 254 +). If you do so, script +execution is stopped after sending out the response and the given exit status is set. The status 0 + means the request +was handled successfully, every other status is considered an error.

    + +
    + +
    +
    diff --git a/doc/guides/usage/usage.html b/doc/guides/usage/usage.html index a1b3555..60926f5 100644 --- a/doc/guides/usage/usage.html +++ b/doc/guides/usage/usage.html @@ -205,7 +205,7 @@ or -

    The logic here is the same as with every PSR-15: HTTP Server Request Handler +

    The logic here is the same as with every PSR-15: HTTP Server Request Handlers middleware: The request gets passed through all middlewares' processRequest() methods in order of their addition to the queue, then a response is created and passed through all processResponse() @@ -348,7 +348,7 @@ $requestHandler->respond();

    To familiarize yourself with the FIFO principle of the middleware queue, you can try to exchange the two lines adding -the middlewares to the queue, i.e. adding MiddlewareTwo +the middlewares to the queue, i.e. add MiddlewareTwo first and MiddlewareOne second. This will result in an HTTP response with status code 500 (Internal Server Error) diff --git a/src/AbstractMiddleware.php b/src/AbstractMiddleware.php index 6577645..451b1cd 100644 --- a/src/AbstractMiddleware.php +++ b/src/AbstractMiddleware.php @@ -99,8 +99,6 @@ abstract class AbstractMiddleware implements MiddlewareInterface * @param RequestHandler $handler The request handler to delegate to * * @return Response The response object - * - * @api */ final public function __invoke(ServerRequest $request, RequestHandler $handler): Response { diff --git a/src/QueueRequestHandler.php b/src/QueueRequestHandler.php index e29a280..5dab177 100644 --- a/src/QueueRequestHandler.php +++ b/src/QueueRequestHandler.php @@ -120,7 +120,6 @@ class QueueRequestHandler implements RequestHandler $exception->getMessage() ) ); - $this->respond(1); } } return $this->response; @@ -129,7 +128,9 @@ class QueueRequestHandler implements RequestHandler /** * Return the current response to the client. * - * @param ?int $exitCode Exit code after sending out the response or NULL to continue + * @param ?int $exitCode Exit status after sending out the response or NULL to continue + * + * Must be in the range 0 to 254. The status 0 is used to terminate the program successfully. * * @return void * @@ -166,6 +167,14 @@ class QueueRequestHandler implements RequestHandler } echo $this->response->getBody(); if (!is_null($exitCode)) { + $options = [ + 'options' => [ + 'default' => 1, + 'min_range' => 0, + 'max_range' => 254 + ] + ]; + $exitCode = filter_var($exitCode, FILTER_VALIDATE_INT, $options); exit($exitCode); } } @@ -226,8 +235,6 @@ class QueueRequestHandler implements RequestHandler * @param ?ServerRequest $request The PSR-7 server request to handle * * @return Response A PSR-7 compatible HTTP response - * - * @api */ public function __invoke(?ServerRequest $request = null): Response {