851c9e145b5af12f48675ccdda55cdcb06c61664
[GitHub/WoltLab/WCF.git] /
1 <?php
2
3 /**
4 * @see https://github.com/laminas/laminas-httphandlerrunner for the canonical source repository
5 * @copyright https://github.com/laminas/laminas-httphandlerrunner/blob/master/COPYRIGHT.md
6 * @license https://github.com/laminas/laminas-httphandlerrunner/blob/master/LICENSE.md New BSD License
7 */
8
9 declare(strict_types=1);
10
11 namespace Laminas\HttpHandlerRunner;
12
13 use Psr\Http\Message\ResponseInterface;
14 use Psr\Http\Message\ServerRequestInterface;
15 use Psr\Http\Server\RequestHandlerInterface;
16 use Throwable;
17
18 /**
19 * "Run" a request handler.
20 *
21 * The RequestHandlerRunner will marshal a request using the composed factory, and
22 * then pass the request to the composed handler. Finally, it emits the response
23 * returned by the handler using the composed emitter.
24 *
25 * If the factory for generating the request raises an exception or throwable,
26 * then the runner will use the composed error response generator to generate a
27 * response, based on the exception or throwable raised.
28 */
29 class RequestHandlerRunner
30 {
31 /**
32 * @var Emitter\EmitterInterface
33 */
34 private $emitter;
35
36 /**
37 * A request handler to run as the application.
38 *
39 * @var RequestHandlerInterface
40 */
41 private $handler;
42
43 /**
44 * A factory capable of generating an error response in the scenario that
45 * the $serverRequestFactory raises an exception during generation of the
46 * request instance.
47 *
48 * The factory will receive the Throwable or Exception that caused the error,
49 * and must return a Psr\Http\Message\ResponseInterface instance.
50 *
51 * @var callable
52 */
53 private $serverRequestErrorResponseGenerator;
54
55 /**
56 * A factory capable of generating a Psr\Http\Message\ServerRequestInterface instance.
57 * The factory will not receive any arguments.
58 *
59 * @var callable
60 */
61 private $serverRequestFactory;
62
63 public function __construct(
64 RequestHandlerInterface $handler,
65 Emitter\EmitterInterface $emitter,
66 callable $serverRequestFactory,
67 callable $serverRequestErrorResponseGenerator
68 ) {
69 $this->handler = $handler;
70 $this->emitter = $emitter;
71
72 // Factories are cast as Closures to ensure return type safety.
73 $this->serverRequestFactory = function () use ($serverRequestFactory) : ServerRequestInterface {
74 return $serverRequestFactory();
75 };
76
77 $this->serverRequestErrorResponseGenerator =
78 function (Throwable $exception) use ($serverRequestErrorResponseGenerator) : ResponseInterface {
79 return $serverRequestErrorResponseGenerator($exception);
80 };
81 }
82
83 /**
84 * Run the application
85 */
86 public function run() : void
87 {
88 try {
89 $request = ($this->serverRequestFactory)();
90 } catch (Throwable $e) {
91 // Error in generating the request
92 $this->emitMarshalServerRequestException($e);
93 return;
94 }
95
96 $response = $this->handler->handle($request);
97
98 $this->emitter->emit($response);
99 }
100
101 private function emitMarshalServerRequestException(Throwable $exception) : void
102 {
103 $response = ($this->serverRequestErrorResponseGenerator)($exception);
104 $this->emitter->emit($response);
105 }
106 }