Passed
Pull Request — master (#391)
by Kirill
05:23
created

RrDispatcher::errorToResponse()   A

Complexity

Conditions 3
Paths 6

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 14
c 0
b 0
f 0
nc 6
nop 1
dl 0
loc 29
rs 9.7998
1
<?php
2
3
/**
4
 * This file is part of Spiral Framework package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Http;
13
14
use Psr\Container\ContainerExceptionInterface;
15
use Psr\Container\ContainerInterface;
16
use Psr\Http\Message\ResponseFactoryInterface;
17
use Psr\Http\Message\ResponseInterface;
18
use Spiral\Boot\DispatcherInterface;
19
use Spiral\Boot\FinalizerInterface;
20
use Spiral\Debug\StateInterface;
21
use Spiral\Exceptions\HtmlHandler;
22
use Spiral\RoadRunner\Environment\Mode;
0 ignored issues
show
Bug introduced by
The type Spiral\RoadRunner\Environment\Mode was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use Spiral\RoadRunner\EnvironmentInterface;
0 ignored issues
show
Bug introduced by
The type Spiral\RoadRunner\EnvironmentInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use Spiral\RoadRunner\Http\PSR7WorkerInterface;
0 ignored issues
show
Bug introduced by
The type Spiral\RoadRunner\Http\PSR7WorkerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use Spiral\Snapshots\SnapshotInterface;
26
use Spiral\Snapshots\SnapshotterInterface;
27
28
class RrDispatcher implements DispatcherInterface
29
{
30
    /**
31
     * @var EnvironmentInterface
32
     */
33
    private $env;
34
35
    /**
36
     * @var PSR7WorkerInterface
37
     */
38
    private $worker;
39
40
    /**
41
     * @var ContainerInterface
42
     */
43
    private $container;
44
45
    /**
46
     * @var FinalizerInterface
47
     */
48
    private $finalizer;
49
50
    /**
51
     * @param EnvironmentInterface $env
52
     * @param PSR7WorkerInterface $worker
53
     * @param ContainerInterface $container
54
     * @param FinalizerInterface $finalizer
55
     */
56
    public function __construct(
57
        EnvironmentInterface $env,
58
        PSR7WorkerInterface $worker,
59
        ContainerInterface $container,
60
        FinalizerInterface $finalizer
61
    ) {
62
        $this->env = $env;
63
        $this->worker = $worker;
64
        $this->container = $container;
65
        $this->finalizer = $finalizer;
66
    }
67
68
    /**
69
     * @return bool
70
     */
71
    public function canServe(): bool
72
    {
73
        return \PHP_SAPI === 'cli' && $this->env->getMode() === Mode::MODE_HTTP;
74
    }
75
76
    /**
77
     * @return void
78
     */
79
    public function serve(): void
80
    {
81
        /** @var Http $http */
82
        $http = $this->container->get(Http::class);
83
84
        while ($request = $this->worker->waitRequest()) {
85
            try {
86
                $response = $http->handle($request);
87
88
                $this->worker->respond($response);
89
            } catch (\Throwable $e) {
90
                $this->worker->respond($this->errorToResponse($e));
91
            } finally {
92
                $this->finalizer->finalize(false);
93
            }
94
        }
95
    }
96
97
    /**
98
     * @param \Throwable $e
99
     * @return ResponseInterface
100
     */
101
    protected function errorToResponse(\Throwable $e): ResponseInterface
102
    {
103
        $handler = new HtmlHandler();
104
105
        try {
106
            /** @var SnapshotInterface $snapshot */
107
            $snapshot = $this->container->get(SnapshotterInterface::class)->register($e);
108
            \file_put_contents('php://stderr', $snapshot->getMessage());
109
110
            // on demand
111
            $state = $this->container->get(StateInterface::class);
112
113
            if ($state !== null) {
114
                $handler = $handler->withState($state);
115
            }
116
        } catch (\Throwable | ContainerExceptionInterface $se) {
117
            \file_put_contents('php://stderr', (string)$e);
118
        }
119
120
        /** @var ResponseFactoryInterface $responseFactory */
121
        $responseFactory = $this->container->get(ResponseFactoryInterface::class);
122
        $response = $responseFactory->createResponse(500);
123
124
        // Reporting system (non handled) exception directly to the client
125
        $response->getBody()->write(
126
            $handler->renderException($e, HtmlHandler::VERBOSITY_VERBOSE)
127
        );
128
129
        return $response;
130
    }
131
}
132