Completed
Push — master ( 9b25f2...d42705 )
by Tomáš
09:42 queued 07:08
created

HttpServer::setupDependencies()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Symplify
7
 * Copyright (c) 2016 Tomas Votruba (http://tomasvotruba.cz).
8
 */
9
10
namespace Symplify\PHP7_Sculpin\HttpServer;
11
12
use React\EventLoop\StreamSelectLoop;
13
use React\Http\Request;
14
use React\Http\Response;
15
use React\Http\Server as ReactHttpServer;
16
use React\Socket\Server as ReactSocketServer;
17
use Symfony\Component\Console\Output\OutputInterface;
18
19
final class HttpServer
20
{
21
    /**
22
     * @var string
23
     */
24
    private $outputDirectory;
25
26
    /**
27
     * @var StreamSelectLoop
28
     */
29
    private $streamSelectLoop;
30
31
    /**
32
     * @var ReactHttpServer
33
     */
34
    private $reactHttpServer;
35
36
    /**
37
     * @var int
38
     */
39
    private $port;
40
41
    /**
42
     * @var ReactSocketServer
43
     */
44
    private $reactSocketServer;
45
46
    /**
47
     * @var OutputInterface
48
     */
49
    private $output;
50
51 1
    public function __construct(string $outputDirectory, OutputInterface $output)
52
    {
53 1
        $this->outputuDirectory = $outputDirectory;
0 ignored issues
show
Bug introduced by
The property outputuDirectory does not seem to exist. Did you mean output?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
54 1
        $this->output = $output;
55 1
    }
56
57 1
    public function init(int $port = 8000)
58
    {
59 1
        $this->setupDependencies();
60
61 1
        $this->port = $port;
62
63 1
        $this->reactHttpServer->on('request', function (Request $request, Response $response) {
64
            $path = $this->outputDirectory.'/'.ltrim(rawurldecode($request->getPath()), '/');
65
            if (is_dir($path)) {
66
                $path .= '/index.html';
67
            }
68
69
            if (!file_exists($path)) {
70
                $this->logRequest('404', $request);
71
                $response->writeHead(404, [
72
                    'Content-Type' => 'text/html',
73
                ]);
74
75
                return $response->end(
76
                    '<h1>404</h1>'.
77
                    '<h2>Not Found</h2>'.
78
                    '<p>'.
79
                    'The embedded <a href="https://sculpin.io">Sculpin</a> web server could not find the requested resource.'.
80
                    '</p>'
81
                );
82
            }
83
84
            $this->logRequest('200', $request);
85
            $response->end(file_get_contents($path));
86 1
        });
87
88 1
        $this->reactSocketServer->listen($this->port, '0.0.0.0');
89 1
    }
90
91 1
    public function addPeriodicTimer(int $interval, callable $callback)
92
    {
93 1
        $this->streamSelectLoop->addPeriodicTimer($interval, $callback);
94 1
    }
95
96
    public function run()
97
    {
98
        $this->output->write(sprintf(
99
            'Starting Sculpin at <info>http://localhost:%s</info>',
100
            $this->port
101
        ));
102
        $this->output->write('Quit the server with <info>CONTROL-C</info>.');
103
104
        $this->streamSelectLoop->run();
105
    }
106
107 1
    private function setupDependencies()
108
    {
109 1
        $this->streamSelectLoop = new StreamSelectLoop();
110 1
        $this->reactSocketServer = new ReactSocketServer($this->streamSelectLoop);
111 1
        $this->reactHttpServer = new ReactHttpServer($this->reactSocketServer);
112 1
    }
113
114
    private function logRequest(string $responseCode, Request $request)
115
    {
116
        $wrapOpen = '';
117
        $wrapClose = '';
118
        if ($responseCode >= 400) {
119
            $wrapOpen = '<error>';
120
            $wrapClose = '</error>';
121
        }
122
123
        $message = sprintf(
124
            '%s for path: "%s"',
125
            $responseCode,
126
            $request->getPath()
127
        );
128
129
        $this->output->write($wrapOpen.$message.$wrapClose);
130
    }
131
}
132