Compare commits

..

No commits in common. "8b51cfccb4d9aa364eec1971b4c554c9236ded00" and "1e4dfd855c6ce9c9b98e6379aff8fae9975e5da3" have entirely different histories.

26 changed files with 187 additions and 267 deletions

View File

@ -30,7 +30,7 @@ jobs:
- name: Upload Artifact
uses: actions/upload-pages-artifact@v3
with:
path: doc/
path: 'doc/'
- name: Deploy to GitHub Pages
id: deployment

View File

@ -30,6 +30,6 @@ jobs:
- name: Run PHPCS
uses: php-actions/phpcs@v1
with:
path: src/
php_version: "8.1"
path: src/
standard: phpcs.xml.dist

View File

@ -23,19 +23,15 @@ jobs:
uses: actions/checkout@v4
- name: Setup Environment
uses: php-actions/composer@v6
uses: shivammathur/setup-php@v2
with:
command: update
php_version: "8.1"
php-version: "8.1"
coverage: none
tools: phpmd
- name: Run PHP Mess Detector
uses: php-actions/phpmd@v1
with:
path: src/
php_version: "8.1"
ruleset: .phpmd.dist.xml
output: sarif
reportfile: phpmd-results.sarif
- name: Run PHPMD
run: phpmd . sarif codesize --reportfile phpmd-results.sarif
continue-on-error: true
- name: Upload Analysis Results
uses: github/codeql-action/upload-sarif@v3

View File

@ -32,5 +32,4 @@ jobs:
uses: php-actions/phpstan@v3
with:
path: src/
php_version: "8.1"
configuration: phpstan.dist.neon

View File

@ -22,12 +22,6 @@ jobs:
- name: Checkout Source Code
uses: actions/checkout@v4
- name: Setup Environment
uses: php-actions/composer@v6
with:
command: update
php_version: "8.1"
- name: Run Psalm
uses: docker://ghcr.io/psalm/psalm-github-actions
with:

2
.gitignore vendored
View File

@ -3,8 +3,6 @@
/vendor/
.php-cs-fixer.cache
.php-cs-fixer.php
.phpmd.result-cache.php
.phpmd.xml
composer.lock
phpcs.xml
phpdoc.xml

View File

@ -6,19 +6,6 @@ Changelog
.. sidebar:: Table of Contents
.. contents::
v1.2.0
======
**Minor Changes:**
* Added a `Warning` header to identify response messages from converted exceptions
* Removed the option to provide an exit status to :php:method:`OCC\PSR15\QueueRequestHandler::respond()`
* Added Composer command for development tools (PHP Mess Detector, Psalm Taint Analysis)
**Maintencance:**
* Updated dependencies
v1.1.0
======

View File

@ -97,10 +97,12 @@ 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. Such a response can be identified by having a `Warning` header set including the error
code and the affected middleware.
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.

View File

@ -19,11 +19,9 @@
your own middleware, but you can just as well use any middleware that implements the middleware interface specified
by PSR-15 (e.g. from the awesome <a href="https://github.com/middlewares">PSR-15 HTTP Middlewares</a> project).</p>
<p>All components of this package follow the highest coding standards of <a href="https://psalm.dev/">Psalm</a>,
<a href="https://phpstan.org/">PHPStan</a>, <a href="https://phpmd.org/">PHP Mess Detector</a>,
<a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/">PHP_CodeSniffer</a>, and comply to
<a href="https://www.php-fig.org/psr/psr-12/">PSR-12</a> code style guidelines to make sure they can be combined
and easily re-used in other projects.</p>
<p>All components of this package follow the highest coding standards of <a href="https://phpstan.org/">PHPStan</a>
and <a href="https://psalm.dev/">Psalm</a>, and comply to <a href="https://www.php-fig.org/psr/psr-12/">PSR-12</a>
code style guidelines to make sure they can be combined and easily re-used in other projects.</p>
<h3 id="toc">Table of Contents</h3>

View File

@ -1,29 +0,0 @@
<?xml version="1.0"?>
<ruleset name="OCC Default PHPMD Ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="
http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
Open Culture Consulting follows PHP Mess Detector standards.
</description>
<rule ref="rulesets/cleancode.xml">
<!-- We need to statically access third-party constructors. -->
<exclude name="StaticAccess" />
</rule>
<rule ref="rulesets/codesize.xml" />
<rule ref="rulesets/controversial.xml">
<exclude name="CamelCaseMethodName" />
</rule>
<rule ref="rulesets/controversial.xml/CamelCaseMethodName">
<properties>
<property name="allow-underscore" value="true" />
</properties>
</rule>
<rule ref="rulesets/design.xml" />
<rule ref="rulesets/naming.xml" />
<rule ref="rulesets/unusedcode.xml" />
</ruleset>

View File

@ -4,7 +4,7 @@
The PHP Standard Recommendation PSR-15 defines interfaces for server request handlers and proposes a queue-based implementation using different middlewares for processing requests and preparing responses. This package follows those guidelines and provides a [HTTP server request handler](src/QueueRequestHandler.php) implementation using a [middleware queue](src/MiddlewareQueue.php). It also contains an [abstract class for middlewares](src/AbstractMiddleware.php) to ease the process of writing your own middleware, but you can just as well use any middleware that implements `Psr\Http\Server\MiddlewareInterface` specified by PSR-15 (e.g. from the awesome [PSR-15 HTTP Middlewares](https://github.com/middlewares) project).
All components of this package follow the highest coding standards of [PHPStan](https://phpstan.org/), [Psalm](https://psalm.dev/), [PHP Mess Detector](https://phpmd.org/), [PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/), and comply to [PSR-12](https://www.php-fig.org/psr/psr-12/) code style guidelines to make sure they can be combined and easily used in other projects.
All components of this package follow the highest coding standards of [PHPStan](https://phpstan.org/) and [Psalm](https://psalm.dev/), and comply to [PSR-12](https://www.php-fig.org/psr/psr-12/) code style guidelines to make sure they can be combined and easily used in other projects.
## Quick Start

View File

@ -30,17 +30,16 @@
},
"require": {
"php": "^8.1",
"guzzlehttp/psr7": "^2.7",
"guzzlehttp/psr7": "^2.6",
"opencultureconsulting/basics": "^2.1",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0"
},
"require-dev": {
"phpdocumentor/shim": "^3.5",
"phpmd/phpmd": "^2.15",
"phpstan/phpstan": "^1.12",
"phpstan/phpstan": "^1.11",
"phpstan/phpstan-strict-rules": "^1.6",
"friendsofphp/php-cs-fixer": "^3.64",
"friendsofphp/php-cs-fixer": "^3.59",
"squizlabs/php_codesniffer": "^3.10",
"vimeo/psalm": "^5.25"
},
@ -71,18 +70,11 @@
"phpdoc:build": [
"@php vendor/bin/phpdoc"
],
"phpmd:check": [
"@php -r \"if (!file_exists('./.phpmd.xml')) { copy('./.phpmd.dist.xml', './.phpmd.xml'); }\"",
"@php vendor/bin/phpmd src/ ansi .phpmd.xml --cache --ignore-violations-on-exit"
],
"phpstan:check": [
"@php vendor/bin/phpstan"
],
"psalm:check": [
"@php vendor/bin/psalm"
],
"psalm:check-security": [
"@php vendor/bin/psalm --taint-analysis"
]
},
"scripts-descriptions": {
@ -90,9 +82,7 @@
"php-cs-fixer:fix": "Runs a code check with PHP Coding Standards Fixer and tries to fix all issues. If a custom configuration file '.php-cs-fixer.php' exists, it will be used instead of the default settings in '.php-cs-fixer.dist.php'.",
"phpcs:check": "Runs a code check with PHP_CodeSniffer and reports problems. If a custom configuration file '.phpcs.xml' exists, it will be used instead of the default settings in '.phpcs.xml.dist'.",
"phpdoc:build": "Builds the documentation from source files in ./src and additional templates in .phpdoc/. If a custom configuration file 'phpdoc.xml' exists, it will be used instead of the default settings in 'phpdoc.dist.xml'.",
"phpmd:check": "Runs a code check with PHP Mess Detector static code analyzer and reports problems. If a custom configuration file '.phpmd.xml' exists, it will be used instead of the default settings in '.phpmd.dist.xml'.",
"phpstan:check": "Runs a code check with PHPStan static code analyzer and reports problems. If a custom configuration file 'phpstan.neon' exists, it will be used instead of the default settings in 'phpstan.dist.neon'.",
"psalm:check": "Runs a code check with Psalm static code analyzer and reports problems. If a custom configuration file 'psalm.xml' exists, it will be used instead of the default settings in 'psalm.xml.dist'.",
"psalm:check-security": "Runs a code check with Psalm static code analyzer and reports security issues. If a custom configuration file 'psalm.xml' exists, it will be used instead of the default settings in 'psalm.xml.dist'."
"psalm:check": "Runs a code check with Psalm static code analyzer and reports problems. If a custom configuration file 'psalm.xml' exists, it will be used instead of the default settings in 'psalm.xml.dist'."
}
}

View File

@ -184,9 +184,9 @@
<aside class="phpdocumentor-element-found-in">
<abbr class="phpdocumentor-element-found-in__file" title="src/QueueRequestHandler.php"><a href="files/src-queuerequesthandler.html"><abbr title="src/QueueRequestHandler.php">QueueRequestHandler.php</abbr></a></abbr>
:
<span class="phpdocumentor-element-found-in__line">53</span>
<span class="phpdocumentor-element-found-in__line">54</span>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.53" class="phpdocumentor-element-found-in__source" data-line="53" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.54" class="phpdocumentor-element-found-in__source" data-line="54" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
</aside>
<p class="phpdocumentor-summary">A queue-based PSR-15 HTTP Server Request Handler.</p>
@ -442,9 +442,9 @@
<aside class="phpdocumentor-element-found-in">
<abbr class="phpdocumentor-element-found-in__file" title="src/QueueRequestHandler.php"><a href="files/src-queuerequesthandler.html"><abbr title="src/QueueRequestHandler.php">QueueRequestHandler.php</abbr></a></abbr>
:
<span class="phpdocumentor-element-found-in__line">215</span>
<span class="phpdocumentor-element-found-in__line">225</span>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.215" class="phpdocumentor-element-found-in__source" data-line="215" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.225" class="phpdocumentor-element-found-in__source" data-line="225" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
</aside>
<p class="phpdocumentor-summary">Create a queue-based PSR-15 HTTP Server Request Handler.</p>
@ -490,9 +490,9 @@
<aside class="phpdocumentor-element-found-in">
<abbr class="phpdocumentor-element-found-in__file" title="src/QueueRequestHandler.php"><a href="files/src-queuerequesthandler.html"><abbr title="src/QueueRequestHandler.php">QueueRequestHandler.php</abbr></a></abbr>
:
<span class="phpdocumentor-element-found-in__line">229</span>
<span class="phpdocumentor-element-found-in__line">239</span>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.229" class="phpdocumentor-element-found-in__source" data-line="229" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.239" class="phpdocumentor-element-found-in__source" data-line="239" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
</aside>
<p class="phpdocumentor-summary">Allow the request handler to be invoked directly.</p>
@ -546,9 +546,9 @@
<aside class="phpdocumentor-element-found-in">
<abbr class="phpdocumentor-element-found-in__file" title="src/QueueRequestHandler.php"><a href="files/src-queuerequesthandler.html"><abbr title="src/QueueRequestHandler.php">QueueRequestHandler.php</abbr></a></abbr>
:
<span class="phpdocumentor-element-found-in__line">93</span>
<span class="phpdocumentor-element-found-in__line">94</span>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.93" class="phpdocumentor-element-found-in__source" data-line="93" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.94" class="phpdocumentor-element-found-in__source" data-line="94" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
</aside>
<p class="phpdocumentor-summary">Handles a request by invoking a queue of middlewares.</p>
@ -604,16 +604,16 @@
<aside class="phpdocumentor-element-found-in">
<abbr class="phpdocumentor-element-found-in__file" title="src/QueueRequestHandler.php"><a href="files/src-queuerequesthandler.html"><abbr title="src/QueueRequestHandler.php">QueueRequestHandler.php</abbr></a></abbr>
:
<span class="phpdocumentor-element-found-in__line">142</span>
<span class="phpdocumentor-element-found-in__line">141</span>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.142" class="phpdocumentor-element-found-in__source" data-line="142" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
<a href="classes/OCC-PSR15-QueueRequestHandler.html#source-view.141" class="phpdocumentor-element-found-in__source" data-line="141" data-modal="source-view" data-src="files/src/QueueRequestHandler.php.txt"></a>
</aside>
<p class="phpdocumentor-summary">Return the current response to the client.</p>
<code class="phpdocumentor-code phpdocumentor-signature ">
<span class="phpdocumentor-signature__visibility">public</span>
<span class="phpdocumentor-signature__name">respond</span><span>(</span><span>)</span><span> : </span><span class="phpdocumentor-signature__response_type">void</span></code>
<span class="phpdocumentor-signature__name">respond</span><span>(</span><span class="phpdocumentor-signature__argument"><span>[</span><span class="phpdocumentor-signature__argument__return-type">int|null&nbsp;</span><span class="phpdocumentor-signature__argument__name">$exitCode</span><span> = </span><span class="phpdocumentor-signature__argument__default-value">null</span><span> ]</span></span><span>)</span><span> : </span><span class="phpdocumentor-signature__response_type">void</span></code>
<div class="phpdocumentor-label-line">
<div class="phpdocumentor-label phpdocumentor-label--success"><span>API</span><span>Yes</span></div>
@ -621,7 +621,20 @@
</div>
<h5 class="phpdocumentor-argument-list__heading">Parameters</h5>
<dl class="phpdocumentor-argument-list">
<dt class="phpdocumentor-argument-list__entry">
<span class="phpdocumentor-signature__argument__name">$exitCode</span>
: <span class="phpdocumentor-signature__argument__return-type">int|null</span>
= <span class="phpdocumentor-signature__argument__default-value">null</span> </dt>
<dd class="phpdocumentor-argument-list__definition">
<section class="phpdocumentor-description"><p>Exit status after sending out the response or NULL to continue</p>
<p>Must be in the range 0 to 254. The status 0 is used to terminate the program successfully.</p>
</section>
</dd>
</dl>
<h5 class="phpdocumentor-tag-list__heading" id="tags">
Tags
@ -758,9 +771,9 @@
<li class="phpdocumentor-on-this-page-section__title">Properties</li>
<li>
<ul class="phpdocumentor-list -clean">
<li class=""><a href="classes/OCC-PSR15-QueueRequestHandler.html#property_queue">$queue</a></li>
<li class=""><a href="classes/OCC-PSR15-QueueRequestHandler.html#property_request">$request</a></li>
<li class=""><a href="classes/OCC-PSR15-QueueRequestHandler.html#property_response">$response</a></li>
<li class=""><a href="classes/OCC-PSR15-QueueRequestHandler.html#property_queue">$queue</li>
<li class=""><a href="classes/OCC-PSR15-QueueRequestHandler.html#property_request">$request</li>
<li class=""><a href="classes/OCC-PSR15-QueueRequestHandler.html#property_response">$response</li>
</ul>
</li>

View File

@ -38,6 +38,7 @@ use function filter_var;
use function get_debug_type;
use function header;
use function headers_sent;
use function is_null;
use function sprintf;
/**
@ -109,18 +110,12 @@ class QueueRequestHandler implements RequestHandler
'max_range' => 599
]
];
$statusCode = filter_var($exception->getCode(), FILTER_VALIDATE_INT, $options);
$this->response = new GuzzleResponse(
filter_var($exception->getCode(), FILTER_VALIDATE_INT, $options),
[
'Warning' => [sprintf(
'Error %d in %s',
$exception->getCode(),
get_debug_type($middleware)
)]
],
$statusCode,
[],
sprintf(
'Exception %d thrown in middleware %s: %s',
$exception->getCode(),
'Exception thrown in middleware %s: %s',
get_debug_type($middleware),
$exception->getMessage()
)
@ -133,13 +128,17 @@ class QueueRequestHandler implements RequestHandler
/**
* Return the current response to the client.
*
* @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
*
* @throws RuntimeException if headers were already sent
*
* @api
*/
public function respond(): void
public function respond(?int $exitCode = null): void
{
$file = 'unknown file';
$line = 0;
@ -167,6 +166,17 @@ class QueueRequestHandler implements RequestHandler
header($header, false);
}
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);
}
}
/**
@ -216,7 +226,7 @@ class QueueRequestHandler implements RequestHandler
{
$this->request = GuzzleRequest::fromGlobals();
$this->queue = MiddlewareQueue::getInstance($middlewares);
$this->response = new GuzzleResponse();
$this->response = new GuzzleResponse(200);
}
/**

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="changelog">
<div class="section" id="changelog">
<h1>Changelog</h1>
<div class="admonition-wrapper">
@ -158,12 +158,6 @@
<div class="contents">
<ul class="phpdocumentor-list">
<li class="toc-item">
<a href="guides/changelog.html#v1-2-0">v1.2.0</a>
</li>
<li class="toc-item">
<a href="guides/changelog.html#v1-1-0">v1.1.0</a>
@ -187,40 +181,7 @@
</div>
</div>
<section class="section " id="v1-2-0">
<h2>v1.2.0</h2>
<p><strong>Minor Changes:</strong>
</p>
<ul>
<li>Added a <code>Warning</code>
header to identify response messages from converted exceptions</li>
<li>Removed the option to provide an exit status to <a href="classes/OCC-PSR15-QueueRequestHandler.html#method_respond"><abbr title="\OCC\PSR15\QueueRequestHandler::respond()">QueueRequestHandler::respond()</abbr></a>
</li>
<li>Added Composer command for development tools (PHP Mess Detector, Psalm Taint Analysis)</li>
</ul>
<p><strong>Maintencance:</strong>
</p>
<ul>
<li>Updated dependencies</li>
</ul>
</section>
<section class="section " id="v1-1-0">
<div class="section" id="v1-1-0">
<h2>v1.1.0</h2>
@ -256,9 +217,9 @@
</ul>
</section>
</div>
<section class="section " id="v1-0-1">
<div class="section" id="v1-0-1">
<h2>v1.0.1</h2>
@ -272,18 +233,18 @@
</ul>
</section>
</div>
<section class="section " id="v1-0-0">
<div class="section" id="v1-0-0">
<h2>v1.0.0</h2>
<p><strong>Initial Release</strong>
</p>
</section>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="documentation">
<div class="section" id="documentation">
<h1>Documentation</h1>
<div class="toc">
@ -209,12 +209,6 @@
<a href="guides/changelog.html#changelog">Changelog</a>
<ul class="section-level-1">
<li class="toc-item">
<a href="guides/changelog.html#v1-2-0">v1.2.0</a>
</li>
<li class="toc-item">
<a href="guides/changelog.html#v1-1-0">v1.1.0</a>
@ -239,7 +233,7 @@
</ul>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="abstractmiddleware">
<div class="section" id="abstractmiddleware">
<h1>AbstractMiddleware</h1>
<div class="admonition-wrapper">
@ -197,11 +197,11 @@ both as needed.</p>
<p>The <code>AbstractMiddleware</code>
implements the <code>Psr\Http\Server\MiddlewareInterface</code>
following PHP-FIG&#039;s recommendation
<a href="https://www.php-fig.org/psr/psr-15/">PSR-15: HTTP Server Request Handlers</a>.</p>
implements the
<a href="https://www.php-fig.org/psr/psr-15/#22-psrhttpservermiddlewareinterface">Psr\Http\Server\MiddlewareInterface</a>
following PHP-FIG&#039;s recommendation <a href="https://www.php-fig.org/psr/psr-15/">PSR-15: HTTP Server Request Handlers</a>.</p>
<section class="section " id="properties">
<div class="section" id="properties">
<h2>Properties</h2>
@ -211,9 +211,9 @@ both as needed.</p>
handler which called the middleware. This can be used to access the request and/or response object (as properties of
<a href="guides/overview/queuerequesthandler.html">QueueRequestHandler</a>) when they are otherwise not available.</p>
</section>
</div>
<section class="section " id="methods">
<div class="section" id="methods">
<h2>Methods</h2>
@ -232,7 +232,7 @@ to receive a response, which is then processed by <a href="classes/OCC-PSR15-Abs
before
returning it back to the request handler again.</p>
<section class="section " id="processing-a-request">
<div class="section" id="processing-a-request">
<h3>Processing a Request</h3>
@ -242,12 +242,11 @@ have to implement your own <code>processRequest()</code>
method. It takes a request object as only argument and must return a
valid request object as well. Just make sure it follows PHP-FIG&#039;s standard recommendation
<a href="https://www.php-fig.org/psr/psr-7/">PSR-7: HTTP Message Interfaces</a> and implements the
<code>Psr\Http\Message\ServerRequestInterface</code>
.</p>
<a href="https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface">Psr\Http\Message\ServerRequestInterface</a>.</p>
</section>
</div>
<section class="section " id="processing-a-response">
<div class="section" id="processing-a-response">
<h3>Processing a Response</h3>
@ -257,14 +256,13 @@ you have to implement your own <code>processResponse()</code>
method. It takes a response object as only argument and must return
a valid response object as well. Just make sure it follows PHP-FIG&#039;s standard recommendation
<a href="https://www.php-fig.org/psr/psr-7/">PSR-7: HTTP Message Interfaces</a> and implements the
<code>Psr\Http\Message\ResponseInterface</code>
.</p>
<a href="https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface">Psr\Http\Message\ResponseInterface</a>.</p>
</section>
</div>
</section>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="overview">
<div class="section" id="overview">
<h1>Overview</h1>
@ -222,7 +222,7 @@ in other projects.</p>
</ul>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="middlewarequeue">
<div class="section" id="middlewarequeue">
<h1>MiddlewareQueue</h1>
<div class="admonition-wrapper">
@ -187,8 +187,7 @@
manages the middlewares involved in processing a server request. It makes sure they are called in
first-in, first-out (FIFO) order, i.e. the same order they were added to the queue. It also ensures all middlewares are
implementing the <a href="https://www.php-fig.org/psr/psr-15/">PSR-15: HTTP Server Request Handlers</a> specification for the
<code>Psr\Http\Server\MiddlewareInterface</code>
.</p>
<a href="https://www.php-fig.org/psr/psr-15/#22-psrhttpservermiddlewareinterface">Psr\Http\Server\MiddlewareInterface</a>.</p>
<p>When instantiating a <code>MiddlewareQueue</code>
@ -216,10 +215,10 @@ $queue-&gt;enqueue(new MiddlewareTwo());</code></pre>
<p>The <code>MiddlewareQueue</code>
is based on a <code>OCC\Basics\DataStructures\StrictQueue</code>
.</p>
is based on a
<a href="https://opencultureconsulting.github.io/php-basics/guides/overview/datastructures.html#strictqueue">OCC\Basics\DataStructures\StrictQueue</a>.</p>
<section class="section " id="methods">
<div class="section" id="methods">
<h2>Methods</h2>
@ -234,7 +233,7 @@ returns the first item from the queue.</p>
<p>For a complete API documentation have a look at the
<a href="https://opencultureconsulting.github.io/php-basics/classes/OCC-Basics-DataStructures-StrictQueue.html">StrictQueue</a>.</p>
<section class="section " id="adding-a-middleware">
<div class="section" id="adding-a-middleware">
<h3>Adding a Middleware</h3>
@ -248,9 +247,9 @@ criterion an <code>OCC\Basics\DataStructures\Exceptions\InvalidDataTypeException
<p>Have a look at the <a href="guides/overview/abstractmiddleware.html">AbstractMiddleware</a> for an easy way to create your own middlewares!</p>
</section>
</div>
<section class="section " id="fetching-the-next-in-line">
<div class="section" id="fetching-the-next-in-line">
<h3>Fetching the next in line</h3>
@ -264,11 +263,11 @@ Also, this middleware is removed from the queue.</p>
)
before trying to dequeue an item!</p>
</section>
</div>
</section>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="queuerequesthandler">
<div class="section" id="queuerequesthandler">
<h1>QueueRequestHandler</h1>
<div class="admonition-wrapper">
@ -215,14 +215,14 @@ a middleware and turns them into a proper HTTP error response.</p>
<p>The <code>QueueRequestHandler</code>
implements the <code>Psr\Http\Server\RequestHandlerInterface</code>
following PHP-FIG&#039;s recommendation
<a href="https://www.php-fig.org/psr/psr-15/">PSR-15: HTTP Server Request Handlers</a>.</p>
implements the
<a href="https://www.php-fig.org/psr/psr-15/#21-psrhttpserverrequesthandlerinterface">Psr\Http\Server\RequestHandlerInterface</a>
following PHP-FIG&#039;s recommendation <a href="https://www.php-fig.org/psr/psr-15/">PSR-15: HTTP Server Request Handlers</a>.</p>
<p>For a minimal working example have a look at <a href="guides/usage/usage.html">Usage</a>.</p>
<section class="section " id="properties">
<div class="section" id="properties">
<h2>Properties</h2>
@ -232,7 +232,7 @@ a middleware and turns them into a proper HTTP error response.</p>
directly accessed from the object via magic methods (e.g. <code>$requestHandler-&gt;queue</code>
).</p>
<section class="section " id="middleware-queue">
<div class="section" id="middleware-queue">
<h3>Middleware Queue</h3>
@ -268,17 +268,16 @@ $requestHandler-&gt;queue-&gt;enqueue(new MiddlewareOne());
$requestHandler-&gt;queue-&gt;enqueue(new MiddlewareTwo());</code></pre>
</blockquote>
</section>
</div>
<section class="section " id="http-server-request">
<div class="section" id="http-server-request">
<h3>HTTP Server Request</h3>
<p>The server request is always available as <code>QueueRequestHandler::request</code>
. It follows PHP-FIG&#039;s standard recommendation
<a href="https://www.php-fig.org/psr/psr-7/">PSR-7: HTTP Message Interfaces</a> and implements the
<code>Psr\Http\Message\ServerRequestInterface</code>
.</p>
<a href="https://www.php-fig.org/psr/psr-7/#321-psrhttpmessageserverrequestinterface">Psr\Http\Message\ServerRequestInterface</a>.</p>
<p>When instantiating a <code>QueueRequestHandler</code>
@ -287,17 +286,16 @@ $requestHandler-&gt;queue-&gt;enqueue(new MiddlewareTwo());</code></pre>
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.</p>
</section>
</div>
<section class="section " id="http-response">
<div class="section" id="http-response">
<h3>HTTP Response</h3>
<p>The response can be read as <code>QueueRequestHandler::response</code>
. It also follows PHP-FIG&#039;s standard recommendation
<a href="https://www.php-fig.org/psr/psr-7/">PSR-7: HTTP Message Interfaces</a> and implements the
<code>Psr\Http\Message\ResponseInterface</code>
.</p>
<a href="https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface">Psr\Http\Message\ResponseInterface</a>.</p>
<p>When instantiating a <code>QueueRequestHandler</code>
@ -310,11 +308,11 @@ always represents the latest state of the response.</p>
<p>Both, request and response, use the awesome implementations of <a href="https://github.com/guzzle/psr7">Guzzle</a>.</p>
</section>
</div>
</section>
</div>
<section class="section " id="methods">
<div class="section" id="methods">
<h2>Methods</h2>
@ -327,7 +325,7 @@ while the latter sends the response back to the client. Invoking the request han
calling the <code>handle()</code>
method.</p>
<section class="section " id="handling-a-server-request">
<div class="section" id="handling-a-server-request">
<h3>Handling a Server Request</h3>
@ -348,24 +346,28 @@ implements <code>Psr\Http\Message\ResponseInterface</code>
<p>In case of an error the request handler catches any exception and creates a response with the exception code as status
code (if it&#039;s within the valid range of HTTP status codes, otherwise it&#039;s set to <code>500 (Internal Server Error)</code>
), and
the exception message as body. Such a response can be identified by having a <code>Warning</code>
header set including the error
code and the affected middleware.</p>
the exception message as body.</p>
</section>
</div>
<section class="section " id="sending-the-response">
<div class="section" id="sending-the-response">
<h3>Sending the Response</h3>
<p>Sending the final response to the client is as easy as calling <a href="classes/OCC-PSR15-QueueRequestHandler.html#method_respond"><abbr title="\OCC\PSR15\QueueRequestHandler::respond()">QueueRequestHandler::respond()</abbr></a>
.</p>
.
Optionally, you can provide an exit code as argument (an integer in the range <code>0</code>
to <code>254</code>
). If you do so, script
execution is stopped after sending out the response and the given exit status is set. The status <code>0</code>
means the request
was handled successfully, every other status is considered an error.</p>
</section>
</div>
</section>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="user-guide">
<div class="section" id="user-guide">
<h1>User Guide</h1>
@ -233,7 +233,7 @@ application. For a detailed description of the package&#039;s contents have a lo
</ul>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="installation">
<div class="section" id="installation">
<h1>Installation</h1>
<div class="admonition-wrapper">
@ -181,7 +181,7 @@
</div>
</div>
<section class="section " id="composer">
<div class="section" id="composer">
<h2>Composer</h2>
@ -203,9 +203,9 @@ composer require &quot;opencultureconsulting/psr15:~1.1&quot;</code></pre>
<p>All available versions as well as further information about <a href="guides/usage/requirements.html">Requirements</a> and dependencies can be found on
<a href="https://packagist.org/packages/opencultureconsulting/psr15">Packagist</a>.</p>
</section>
</div>
<section class="section " id="git">
<div class="section" id="git">
<h2>Git</h2>
@ -227,18 +227,18 @@ git clone --branch=v1.1.0 https://github.com/opencultureconsulting/psr-15.git ps
<p>Be aware that you also need to make the classes available in your application by either adding them to your autoloader
or by including all files individually in PHP. Also don&#039;t forget to do the same for all <a href="guides/usage/requirements.html">Requirements</a>.</p>
</section>
</div>
<section class="section " id="download">
<div class="section" id="download">
<h2>Download</h2>
<p>As a last resort you can also just download the files. You can find all available versions as well as the current
development state on the <a href="https://github.com/opencultureconsulting/psr-15/releases">GitHub release page</a>.</p>
</section>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,10 +150,10 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="requirements">
<div class="section" id="requirements">
<h1>Requirements</h1>
<section class="section " id="environment">
<div class="section" id="environment">
<h2>Environment</h2>
@ -165,9 +165,9 @@
although it is technically not strictly required for using any of these classes. But it certainly makes it a lot
easier!</p>
</section>
</div>
<section class="section " id="dependencies">
<div class="section" id="dependencies">
<h2>Dependencies</h2>
@ -184,9 +184,9 @@ of the great <a href="https://packagist.org/packages/guzzlehttp/psr7">guzzlehttp
of the <a href="https://packagist.org/packages/opencultureconsulting/basics">opencultureconsulting/basics</a> package which also
provides some useful traits.</p>
</section>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

View File

@ -150,7 +150,7 @@
</aside>
<div class="phpdocumentor-column -nine phpdocumentor-content">
<section class="section " id="usage">
<div class="section" id="usage">
<h1>Usage</h1>
<div class="admonition-wrapper">
@ -188,7 +188,7 @@
and <code>MiddlewareTwo</code>
).</p>
<section class="section " id="middlewares">
<div class="section" id="middlewares">
<h2>Middlewares</h2>
@ -304,9 +304,9 @@ class MiddlewareTwo extends AbstractMiddleware
<p>Well done! We now have two middlewares.</p>
</section>
</div>
<section class="section " id="request-handler">
<div class="section" id="request-handler">
<h2>Request Handler</h2>
@ -341,9 +341,9 @@ $requestHandler-&gt;respond();
<p>And that&#039;s it!</p>
</section>
</div>
<section class="section " id="diving-deeper">
<div class="section" id="diving-deeper">
<h2>Diving Deeper</h2>
@ -365,9 +365,9 @@ is not <code>MiddlewareTwo</code>
response status code to <code>500</code>
.</p>
</section>
</div>
</section>
</div>
</div>
<section data-search-results class="phpdocumentor-search-results phpdocumentor-search-results--hidden">

8
doc/index.html generated
View File

@ -167,11 +167,9 @@
your own middleware, but you can just as well use any middleware that implements the middleware interface specified
by PSR-15 (e.g. from the awesome <a href="https://github.com/middlewares">PSR-15 HTTP Middlewares</a> project).</p>
<p>All components of this package follow the highest coding standards of <a href="https://psalm.dev/">Psalm</a>,
<a href="https://phpstan.org/">PHPStan</a>, <a href="https://phpmd.org/">PHP Mess Detector</a>,
<a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/">PHP_CodeSniffer</a>, and comply to
<a href="https://www.php-fig.org/psr/psr-12/">PSR-12</a> code style guidelines to make sure they can be combined
and easily re-used in other projects.</p>
<p>All components of this package follow the highest coding standards of <a href="https://phpstan.org/">PHPStan</a>
and <a href="https://psalm.dev/">Psalm</a>, and comply to <a href="https://www.php-fig.org/psr/psr-12/">PSR-12</a>
code style guidelines to make sure they can be combined and easily re-used in other projects.</p>
<h3 id="toc">Table of Contents</h3>

View File

@ -38,6 +38,7 @@ use function filter_var;
use function get_debug_type;
use function header;
use function headers_sent;
use function is_null;
use function sprintf;
/**
@ -109,18 +110,12 @@ class QueueRequestHandler implements RequestHandler
'max_range' => 599
]
];
$statusCode = filter_var($exception->getCode(), FILTER_VALIDATE_INT, $options);
$this->response = new GuzzleResponse(
filter_var($exception->getCode(), FILTER_VALIDATE_INT, $options),
[
'Warning' => [sprintf(
'Error %d in %s',
$exception->getCode(),
get_debug_type($middleware)
)]
],
$statusCode,
[],
sprintf(
'Exception %d thrown in middleware %s: %s',
$exception->getCode(),
'Exception thrown in middleware %s: %s',
get_debug_type($middleware),
$exception->getMessage()
)
@ -133,13 +128,17 @@ class QueueRequestHandler implements RequestHandler
/**
* Return the current response to the client.
*
* @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
*
* @throws RuntimeException if headers were already sent
*
* @api
*/
public function respond(): void
public function respond(?int $exitCode = null): void
{
$file = 'unknown file';
$line = 0;
@ -167,6 +166,17 @@ class QueueRequestHandler implements RequestHandler
header($header, false);
}
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);
}
}
/**
@ -216,7 +226,7 @@ class QueueRequestHandler implements RequestHandler
{
$this->request = GuzzleRequest::fromGlobals();
$this->queue = MiddlewareQueue::getInstance($middlewares);
$this->response = new GuzzleResponse();
$this->response = new GuzzleResponse(200);
}
/**