Completed
Push — master ( 91bd08...d24b22 )
by Tomáš
11s
created

HttpServer   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 7
dl 0
loc 146
ccs 0
cts 85
cp 0
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 1
B init() 0 45 5
A addPeriodicTimer() 0 4 1
A run() 0 12 1
A setupDependencies() 0 6 1
A logRequest() 0 20 2
1
<?php
2
3
/*
4
 * This file is a part of Sculpin.
5
 *
6
 * (c) Dragonfly Development Inc.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Symplify\PHP7_Sculpin\Bundle\SculpinBundle\HttpServer;
13
14
use Dflydev\ApacheMimeTypes\PhpRepository;
15
use React\EventLoop\StreamSelectLoop;
16
use React\Http\Request;
17
use React\Http\Response;
18
use React\Http\Server as ReactHttpServer;
19
use React\Socket\Server as ReactSocketServer;
20
use Symplify\PHP7_Sculpin\Core\Io\ConsoleIo;
21
22
final class HttpServer
23
{
24
    /**
25
     * @var ConsoleIo
26
     */
27
    private $consoleIo;
28
29
    /**
30
     * @var string
31
     */
32
    private $outputDirectory;
33
34
    /**
35
     * @var PhpRepository
36
     */
37
    private $phpRepository;
38
39
    /**
40
     * @var StreamSelectLoop
41
     */
42
    private $streamSelectLoop;
43
44
    /**
45
     * @var ReactHttpServer
46
     */
47
    private $reactHttpServer;
48
49
    /**
50
     * @var int
51
     */
52
    private $port;
53
54
    /**
55
     * @var ReactSocketServer
56
     */
57
    private $reactSocketServer;
58
59
    public function __construct(
60
        string $outputDirectory,
61
        ConsoleIo $consoleIo,
62
        PhpRepository $phpRepository
63
//        StreamSelectLoop $streamSelectLoop,
64
//        ReactSocketServer $reactSocketServer,
65
//        ReactHttpServer $reactHttpServer
66
)
67
    {
68
        $this->outputDirectory = $outputDirectory;
69
        $this->consoleIo = $consoleIo;
70
        $this->phpRepository = $phpRepository;
71
//        $this->streamSelectLoop = $streamSelectLoop;
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
72
//        $this->socketServer = $reactSocketServer;
73
//        $this->reactHttpServer = $reactHttpServer;
74
    }
75
76
    public function init(int $port = 8000)
77
    {
78
        $this->setupDependencies();
79
80
        $this->port = $port;
81
82
        $this->reactHttpServer->on('request', function (Request $request, Response $response) {
83
            $path = $this->outputDirectory.'/'.ltrim(rawurldecode($request->getPath()), '/');
84
            if (is_dir($path)) {
85
                $path .= '/index.html';
86
            }
87
88
            if (!file_exists($path)) {
89
                $this->logRequest(404, $request);
90
                $response->writeHead(404, [
91
                    'Content-Type' => 'text/html',
92
                ]);
93
94
                return $response->end(
95
                    '<h1>404</h1>'.
96
                    '<h2>Not Found</h2>'.
97
                    '<p>'.
98
                    'The embedded <a href="https://sculpin.io">Sculpin</a> web server could not find the requested resource.'.
99
                    '</p>'
100
                );
101
            }
102
103
            $type = 'application/octet-stream';
104
105
            if ('' !== $extension = pathinfo($path, PATHINFO_EXTENSION)) {
106
                if ($guessedType = $this->phpRepository->findType($extension)) {
107
                    $type = $guessedType;
108
                }
109
            }
110
111
            $this->logRequest(200, $request);
112
113
            $response->writeHead(200, [
114
                'Content-Type' => $type,
115
            ]);
116
            $response->end(file_get_contents($path));
117
        });
118
119
        $this->reactSocketServer->listen($this->port, '0.0.0.0');
120
    }
121
122
    public function addPeriodicTimer(int $interval, callable $callback)
123
    {
124
        $this->streamSelectLoop->addPeriodicTimer($interval, $callback);
125
    }
126
127
    public function run()
128
    {
129
        $this->consoleIo->write('Starting Sculpin server.');
130
        $this->consoleIo->write(sprintf(
131
            'Server is running at <info>http://%s:%s</info>',
132
            'localhost',
133
            $this->port
134
        ));
135
        $this->consoleIo->write('Quit the server with CONTROL-C.');
136
137
        $this->streamSelectLoop->run();
138
    }
139
140
    private function setupDependencies()
141
    {
142
        $this->streamSelectLoop = new StreamSelectLoop();
143
        $this->reactSocketServer = new ReactSocketServer($this->streamSelectLoop);
144
        $this->reactHttpServer = new ReactHttpServer($this->reactSocketServer);
145
    }
146
147
    private function logRequest(string $responseCode, Request $request)
148
    {
149
        $wrapOpen = '';
150
        $wrapClose = '';
151
        if ($responseCode >= 400) {
152
            $wrapOpen = '<comment>';
153
            $wrapClose = '</comment>';
154
        }
155
156
        $message = sprintf(
157
            '[%s] "%s %s HTTP/%s" %s',
158
            date('d/M/Y H:i:s'),
159
            $request->getMethod(),
160
            $request->getPath(),
161
            $request->getHttpVersion(),
162
            $responseCode
163
        );
164
165
        $this->consoleIo->write($wrapOpen.$message.$wrapClose);
166
    }
167
}
168