HttpRouter::isOriginAllowed()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Dazzle\Http\Http\Component\Router;
4
5
use Dazzle\Http\Http\HttpRequestInterface;
6
use Dazzle\Http\Http\HttpResponse;
7
use Dazzle\Http\NetworkComponentAwareInterface;
8
use Dazzle\Http\NetworkConnectionInterface;
9
use Dazzle\Http\NetworkMessageInterface;
10
use Dazzle\Http\NetworkComponentInterface;
11
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
12
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
13
use Symfony\Component\Routing\Matcher\UrlMatcher;
14
use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
15
use Symfony\Component\Routing\RequestContext;
16
use Symfony\Component\Routing\Route;
17
use Symfony\Component\Routing\RouteCollection;
18
use Error;
19
use Exception;
20
21
class HttpRouter implements HttpRouterInterface
22
{
23
    /**
24
     * @var RouteCollection
25
     */
26
    protected $routes;
27
28
    /**
29
     * @var RequestContext
30
     */
31
    protected $context;
32
33
    /**
34
     * @var UrlMatcherInterface
35
     */
36
    protected $matcher;
37
38
    /**
39
     * @var string
40
     */
41
    protected $host;
42
43
    /**
44
     * @var bool
45
     */
46
    protected $checkOrigin;
47
48
    /**
49
     * @var string[]
50
     */
51
    protected $allowedOrigins;
52
53
    /**
54
     * @param NetworkComponentAwareInterface $aware
55
     * @param mixed[] $params
56
     */
57 49
    public function __construct(NetworkComponentAwareInterface $aware = null, $params = [])
58
    {
59 49
        $this->routes = (isset($params['routes']) && $params['routes'] instanceof RouteCollection)
60
            ? $params['routes']
61 49
            : new RouteCollection();
62 49
        $this->context = (isset($params['context']) && $params['context'] instanceof RequestContext)
63
            ? $params['context']
64 49
            : new RequestContext();
65
66 49
        $this->matcher = new UrlMatcher(
67 49
            $this->routes,
68 49
            $this->context
69
        );
70
71 49
        $this->host = isset($params['host']) ? $params['host'] : 'localhost';
72 49
        $this->checkOrigin = isset($params['checkOrigin']) ? $params['checkOrigin'] : false;
73 49
        $this->allowedOrigins = [];
74
75 49
        if ($aware !== null)
76
        {
77 49
            $aware->setComponent($this);
78
        }
79 49
    }
80
81
    /**
82
     *
83
     */
84
    public function __destruct()
85
    {
86
        unset($this->routes);
87
        unset($this->matcher);
88
        unset($this->matcher);
89
        unset($this->params);
90
        unset($this->checkOrigin);
91
        unset($this->allowedOrigins);
92
    }
93
94
    /**
95
     * @override
96
     * @inheritDoc
97
     */
98 5
    public function allowOrigin($address)
99
    {
100 5
        $this->allowedOrigins[$address] = true;
101
102 5
        return $this;
103
    }
104
105
    /**
106
     * @override
107
     * @inheritDoc
108
     */
109 2
    public function disallowOrigin($address)
110
    {
111 2
        if (isset($this->allowedOrigins[$address]))
112
        {
113 2
            unset($this->allowedOrigins[$address]);
114
        }
115
116 2
        return $this;
117
    }
118
119
    /**
120
     * @override
121
     * @inheritDoc
122
     */
123 3
    public function isOriginAllowed($address)
124
    {
125 3
        return isset($this->allowedOrigins[$address]);
126
    }
127
128
    /**
129
     * @override
130
     * @inheritDoc
131
     */
132 1
    public function getAllowedOrigins()
133
    {
134 1
        return array_keys($this->allowedOrigins);
135
    }
136
137
    /**
138
     * @override
139
     * @inheritDoc
140
     */
141 6
    public function existsRoute($path)
142
    {
143 6
        return $this->routes->get($path) !== null;
144
    }
145
146
    /**
147
     * @override
148
     * @inheritDoc
149
     */
150 6
    public function addRoute($path, NetworkComponentInterface $component)
151
    {
152 6
        $this->routes->add(
153 6
            $path,
154 6
            new Route(
155 6
                $path,
156 6
                [ '_controller' => $component ],
157 6
                $this->checkOrigin ? [ 'Origin' => $this->host ] : [],
158 6
                [],
159 6
                $this->checkOrigin ? $this->host : ''
160
            )
161
        );
162
163 6
        return $this;
164
    }
165
166
    /**
167
     * @override
168
     * @inheritDoc
169
     */
170 2
    public function removeRoute($path)
171
    {
172 2
        $this->routes->remove($path);
173
174 2
        return $this;
175
    }
176
177
    /**
178
     * @override
179
     * @inheritDoc
180
     */
181 3
    public function handleConnect(NetworkConnectionInterface $conn)
182 3
    {}
183
184
    /**
185
     * @override
186
     * @inheritDoc
187
     */
188 4
    public function handleDisconnect(NetworkConnectionInterface $conn)
189
    {
190 4
        if (isset($conn->controller))
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
191
        {
192 3
            $conn->controller->handleDisconnect($conn);
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
193
        }
194 4
    }
195
196
    /**
197
     * @override
198
     * @inheritDoc
199
     */
200 10
    public function handleMessage(NetworkConnectionInterface $conn, NetworkMessageInterface $message)
201
    {
202 10
        if (!$message instanceof HttpRequestInterface)
203
        {
204 2
            if (!isset($conn->controller))
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
205
            {
206 1
                return $this->close($conn, 500);
207
            }
208
209 1
            return $conn->controller->handleMessage($conn, $message);
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
210
        }
211
212 8
        if ($this->checkOrigin && ($header = $message->getHeaderLine('Origin')) !== '')
213
        {
214 1
            $origin = parse_url($header, PHP_URL_HOST) ?: $header;
215
216 1
            if ($origin !== '' && !$this->isOriginAllowed($origin))
217
            {
218 1
                return $this->close($conn, 403);
219
            }
220
        }
221
222 7
        $context = $this->matcher->getContext();
223 7
        $context->setMethod($message->getMethod());
224 7
        $context->setHost($message->getUri()->getHost());
225 7
        $route = [];
226
227
        try
228
        {
229 7
            $route = $this->matcher->match($message->getUri()->getPath());
230
        }
231 3
        catch (MethodNotAllowedException $nae)
232
        {
233 1
            return $this->close($conn, 403);
234
        }
235 2
        catch (ResourceNotFoundException $nfe)
236
        {
237 1
            return $this->close($conn, 404);
238
        }
239 1
        catch (Error $ex)
240
        {
241
            return $this->close($conn, 500);
242
        }
243 1
        catch (Exception $ex)
244
        {
245 1
            return $this->close($conn, 500);
246
        }
247
248 4
        $conn->controller = $route['_controller'];
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
249
250
        try
251
        {
252 4
            $conn->controller->handleConnect($conn);
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
253 3
            $conn->controller->handleMessage($conn, $message);
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
254 3
            return;
255
        }
256 1
        catch (Error $ex)
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
257
        {}
258 1
        catch (Exception $ex)
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
259
        {}
260
261 1
        $conn->controller->handleError($conn, $ex);
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
262 1
    }
263
264
    /**
265
     * @override
266
     * @inheritDoc
267
     */
268 3
    public function handleError(NetworkConnectionInterface $conn, $ex)
269
    {
270 3
        if (isset($conn->controller))
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
271
        {
272
            try
273
            {
274 2
                return $conn->controller->handleError($conn, $ex);
0 ignored issues
show
Bug introduced by
Accessing controller on the interface Dazzle\Http\NetworkConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
275
            }
276 1
            catch (Error $ex)
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
277
            {}
278 1
            catch (Exception $ex)
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
279
            {}
280
        }
281
282 2
        $this->close($conn, 500);
283 2
    }
284
285
    /**
286
     * Close a connection with an HTTP response.
287
     *
288
     * @param NetworkConnectionInterface $conn
289
     * @param int $code
290
     * @return null
291
     */
292 1
    protected function close(NetworkConnectionInterface $conn, $code = 400)
293
    {
294 1
        $response = new HttpResponse($code);
295
296 1
        $conn->send($response);
297 1
        $conn->close();
298 1
    }
299
}
300