Skip to content

Commit cfd5d5f

Browse files
committed
Documentation for consuming response from next request handler function
1 parent 505dd30 commit cfd5d5f

1 file changed

Lines changed: 74 additions & 4 deletions

File tree

README.md

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -798,10 +798,27 @@ As such, this project supports the concept of middleware request handlers.
798798

799799
A middleware request handler is expected to adhere the following rules:
800800

801-
* It is a `callable`.
802-
* It accepts `ServerRequestInterface` as first argument and optional `callable` as second argument.
803-
* It returns a `ResponseInterface` (or any promise which can be consumed by [`Promise\resolve`](http://reactphp.org/promise/#resolve) resolving to a `ResponseInterface`)
804-
* It calls `$next($request)` to continue processing the next middleware function or returns explicitly to abort the chain
801+
* It is a valid `callable`.
802+
* It accepts `ServerRequestInterface` as first argument and an optional
803+
`callable` as second argument.
804+
* It returns either:
805+
* An instance implementing `ResponseInterface` for direct consumption.
806+
* Any promise which can be consumed by
807+
[`Promise\resolve()`](http://reactphp.org/promise/#resolve) resolving to a
808+
`ResponseInterface` for deferred consumption.
809+
* It MAY throw an `Exception` (or return a rejected promise) in order to
810+
signal an error condition and abort the chain.
811+
* It calls `$next($request)` to continue processing the next middleware
812+
request handler function or returns explicitly without calling `$next` to
813+
abort the chain.
814+
* The `$next` request handler function (recursively) invokes the next request
815+
handler from the chain with the same logic as above and returns (or throws)
816+
as above.
817+
* The `$request` may be modified prior to calling `$next($request)` to
818+
change the incoming request the next middleware operates on.
819+
* The `$next` return value may be consumed to modify the outgoing response.
820+
* The `$next` request handler MAY be called more than once if you want to
821+
implement custom "retry" logic etc.
805822

806823
Note that this very simple definition allows you to use either anonymous
807824
functions or any classes that use the magic `__invoke()` method.
@@ -828,9 +845,62 @@ $server = new Server(array(
828845
$request = $request->withHeader('Request-Time', time());
829846
return $next($request);
830847
},
848+
function (ServerRequestInterface $request) {
849+
return new Response(200);
850+
}
851+
));
852+
```
853+
854+
Similarly, you can use the result of the `$next` middleware request handler
855+
function to modify the outgoing response.
856+
Note that as per the above documentation, the `$next` method may return a
857+
`ResponseInterface` directly or one wrapped in a promise for deferred
858+
resolution.
859+
In order to simplify handling both paths, you can simply wrap this in a
860+
[`Promise\resolve()`](http://reactphp.org/promise/#resolve) call like this:
861+
862+
```php
863+
$server = new Server(array(
831864
function (ServerRequestInterface $request, callable $next) {
865+
$promise = React\Promise\resolve($next($request));
866+
return $promise->then(function (ResponseInterface $response) {
867+
return $response->withHeader('Content-Type', 'text/html');
868+
});
869+
},
870+
function (ServerRequestInterface $request) {
832871
return new Response(200);
872+
}
873+
));
874+
```
875+
876+
Note that the `$next` middleware request handler function may also throw an
877+
`Exception` (or return a rejected promise) as described above.
878+
The previous example does not catch any exceptions and would thus signal an
879+
error condition to the `Server`.
880+
Alternatively, you can also catch any `Exception` to implement custom error
881+
handling logic (or logging etc.) by wrapping this in a
882+
[`Promise`](http://reactphp.org/promise/#promise) like this:
883+
884+
```php
885+
$server = new Server(array(
886+
function (ServerRequestInterface $request, callable $next) {
887+
$promise = new React\Promise\Promise(function ($resolve) use ($next, $request) {
888+
$resolve($next($request));
889+
});
890+
return $promise->then(null, function (Exception $e) {
891+
return new Response(
892+
500,
893+
array(),
894+
'Internal error: ' . $e->getMessage()
895+
);
896+
});
833897
},
898+
function (ServerRequestInterface $request) {
899+
if (mt_rand(0, 1) === 1) {
900+
throw new RuntimeException('Database error');
901+
}
902+
return new Response(200);
903+
}
834904
));
835905
```
836906

0 commit comments

Comments
 (0)