Completed
Pull Request — master (#100)
by Maxime
02:33
created

Request::setHost()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
/**
4
 * This file is a part of a nekland library
5
 *
6
 * (c) Nekland <[email protected]>
7
 *
8
 * For the full license, take a look to the LICENSE file
9
 * on the root directory of this project
10
 */
11
12
namespace Nekland\Woketo\Http;
13
14
use Nekland\Woketo\Exception\HttpException;
15
16
class Request extends AbstractHttpMessage
17
{
18
    /**
19
     * @var string
20
     */
21
    private $method;
22
23
    /**
24
     * @var string
25
     */
26
    private $uri;
27
28
    /**
29
     * @var string
30
     */
31
    private $host;
32
33
    private function __construct() {}
34
35
    /**
36
     * @return Request
37
     */
38 8
    private function setMethod($method) : Request
39
    {
40 8
        $this->method = $method;
41
42 8
        return $this;
43
    }
44
45
    /**
46
     * @param string $uri
47
     * @return Request
48
     */
49 8
    private function setUri(string $uri) : Request
50
    {
51 8
        $this->uri = $uri;
52
53 8
        return $this;
54
    }
55
56
    /**
57
     * @return string
58
     */
59 6
    public function getUri() : string
60
    {
61 6
        return $this->uri;
62
    }
63
64
    /**
65
     * @return string
66
     */
67 4
    public function getMethod() : string
68
    {
69 4
        return $this->method;
70
    }
71
72
    /**
73
     * @return int
74
     */
75 1
    public function getVersion() : int
76
    {
77 1
        return (int) $this->getHeaders()->get('Sec-WebSocket-Version');
78
    }
79
80
    /**
81
     * @param string $host
82
     * @return self
83
     */
84 1
    private function setHost(string $host) : Request
85
    {
86 1
        $this->host = $host;
87
88 1
        return $this;
89
    }
90
91
    /**
92
     * @return array
93
     */
94 2
    public function getExtensions() : array
95
    {
96 2
        $originalHeaders = $this->getHeaders()->get('Sec-WebSocket-Extensions');
97 2
        if (!\is_array($originalHeaders)) {
98 1
            $originalHeaders = [$originalHeaders];
99
        }
100
101 2
        $extensionHeaders = [];
102 2
        $extensions = [];
103
104 2
        foreach ($originalHeaders as $extensionHeader) {
105 2
            $extensionHeaders = \array_merge($extensionHeaders, \array_map('trim', \explode(',', $extensionHeader)));
106
        }
107
108 2
        foreach ($extensionHeaders as $extension) {
109 2
            $explodingHeader = \explode(';', $extension);
110 2
            $extensionName = \trim($explodingHeader[0]);
111 2
            $extensions[$extensionName] = [];
112
113 2
            if (\count($explodingHeader)) {
114 2
                unset($explodingHeader[0]); // removing the name of the extension
115 2
                foreach($explodingHeader as $variable) {
116 1
                    $explodeVariable = \explode('=', $variable);
117
118
                    // The value can be with or without quote. We need to remove extra quotes.
119 1
                    $value = \preg_replace('/^"(.+)"$/', '$1', trim($explodeVariable[1]));
120 1
                    $value = \str_replace('\\"', '"', $value);
121
122 2
                    $extensions[$extensionName][\trim($explodeVariable[0])] = $value;
123
                }
124
            }
125
        }
126
127 2
        return $extensions;
128
    }
129
130
    /**
131
     * @param string $requestString
132
     * @return Request
133
     * @throws HttpException
134
     */
135 10
    public static function create(string $requestString)
136
    {
137 10
        $request = new Request;
138
139 10
        $lines = \explode("\r\n", $requestString);
140 10
        Request::initRequest($lines[0], $request);
141
142 7
        unset($lines[0]);
143 7
        Request::initHeaders($lines, $request);
144
145 7
        if (empty($request->getHeaders()->get('Sec-WebSocket-Key')) || empty($request->getHeaders()->get('Upgrade')) || \strtolower($request->getHeaders()->get('Upgrade')) !== 'websocket') {
146
            throw new HttpException(sprintf("The request is not a websocket upgrade request, received:\n%s", $requestString));
147
        }
148
149 7
        return $request;
150
    }
151
152
    /**
153
     * @param string $uri
154
     * @param string $host
155
     * @return Request
156
     */
157 1
    public static function createClientRequest(string $uri, string $host)
158
    {
159 1
        $request = new Request();
160
161 1
        $request->setMethod('GET');
162 1
        $request->setUri($uri);
163 1
        $request->setHttpVersion('1.1');
164 1
        $request->setHost($host);
165
166 1
        return $request;
167
    }
168
169
    /**
170
     * @param string  $firstLine
171
     * @param Request $request
172
     * @throws HttpException
173
     */
174 10
    protected static function initRequest(string $firstLine, Request $request)
175
    {
176 10
        $httpElements = \explode(' ', $firstLine);
177
178 10
        if (\count($httpElements) < 3) {
179 1
            throw Request::createNotHttpException($firstLine);
180
        }
181
182 9
        $httpElements[2] = \trim($httpElements[2]);
183 9
        if (!\preg_match('/HTTP\/.+/', $httpElements[2])) {
184 1
            throw Request::createNotHttpException($firstLine);
185
        }
186 8
        $request->setHttpVersion($httpElements[2]);
187
188 8
        if (!\in_array($httpElements[0], ['POST', 'GET', 'PUT', 'DELETE'])) {
189 1
            throw new HttpException(
190 1
                \sprintf('Request not supported, only POST, GET, PUT, and DELETE are supported. "%s" received.', $httpElements[0])
191
            );
192
        }
193
194 7
        $request->setMethod($httpElements[0]);
195 7
        $request->setUri($httpElements[1]);
196 7
    }
197
198 2
    private static function createNotHttpException($line)
199
    {
200 2
        return new HttpException(
201 2
            \sprintf('The request is not an http request. "%s" received.', $line)
202
        );
203
    }
204
205 7
    protected static function initHeaders(array $headers, Request $request)
206
    {
207 7
        foreach ($headers as $header) {
208 7
            $cuttedHeader = \explode(':', $header);
209 7
            $request->addHeader(\trim($cuttedHeader[0]), trim(str_replace($cuttedHeader[0] . ':', '', $header)));
210
        }
211 7
    }
212
}
213