This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Anax\Route; |
||
4 | |||
5 | use Anax\Commons\ContainerInjectableInterface; |
||
6 | use Anax\Commons\ContainerInjectableTrait; |
||
7 | use Anax\Route\Exception\ConfigurationException; |
||
8 | use Anax\Route\Exception\ForbiddenException; |
||
9 | use Anax\Route\Exception\InternalErrorException; |
||
10 | use Anax\Route\Exception\NotFoundException; |
||
11 | |||
12 | /** |
||
13 | * A router to hold and match routes. |
||
14 | */ |
||
15 | class Router implements ContainerInjectableInterface |
||
16 | { |
||
17 | use ContainerInjectableTrait; |
||
18 | |||
19 | |||
20 | |||
21 | /** |
||
22 | * @var array $routes all the routes. |
||
23 | * @var array $internalRoutes all internal routes. |
||
24 | * @var Route $lastRoute last route that was matched and called. |
||
25 | * @var string $errorMessage last error message for internal routes. |
||
26 | */ |
||
27 | private $routes = []; |
||
28 | private $internalRoutes = []; |
||
29 | private $lastRoute = null; |
||
30 | private $errorMessage = null; |
||
31 | |||
32 | |||
33 | |||
34 | /** |
||
35 | * @const DEVELOPMENT Verbose with exceptions. |
||
36 | * @const PRODUCTION Exceptions turns into 500. |
||
37 | */ |
||
38 | const DEVELOPMENT = 0; |
||
39 | const PRODUCTION = 1; |
||
40 | |||
41 | |||
42 | |||
43 | /** |
||
44 | * @var integer $mode current mode. |
||
45 | */ |
||
46 | private $mode = self::DEVELOPMENT; |
||
47 | |||
48 | |||
49 | |||
50 | /** |
||
51 | * Set Router::DEVELOPMENT or Router::PRODUCTION mode. |
||
52 | * |
||
53 | * @param integer $mode which mode to set. |
||
54 | * |
||
55 | * @return self to enable chaining. |
||
56 | */ |
||
57 | 4 | public function setMode($mode) : object |
|
58 | { |
||
59 | 4 | $this->mode = $mode; |
|
60 | 4 | return $this; |
|
61 | } |
||
62 | |||
63 | |||
64 | |||
65 | /** |
||
66 | * Add routes from an array where the array looks like this: |
||
67 | * [ |
||
68 | * "mount" => null|string, // Where to mount the routes |
||
69 | * "routes" => [ // All routes in this array |
||
70 | * [ |
||
71 | * "info" => "Just say hi.", |
||
72 | * "method" => null, |
||
73 | * "path" => "hi", |
||
74 | * "handler" => function () { |
||
75 | * return "Hi."; |
||
76 | * }, |
||
77 | * ] |
||
78 | * ] |
||
79 | * ] |
||
80 | * |
||
81 | * @throws ConfigurationException |
||
82 | * |
||
83 | * @param array $routes containing the routes to add. |
||
84 | * |
||
85 | * @return self to enable chaining. |
||
86 | */ |
||
87 | 23 | public function addRoutes(array $routes) : object |
|
88 | { |
||
89 | 23 | if (!(isset($routes["routes"]) && is_array($routes["routes"]))) { |
|
90 | 3 | throw new ConfigurationException("No routes found, missing key 'routes' in configuration array."); |
|
91 | } |
||
92 | |||
93 | 20 | foreach ($routes["routes"] as $route) { |
|
94 | 19 | if ($route["internal"] ?? false) { |
|
95 | 11 | $this->addInternalRoute( |
|
96 | 11 | $route["path"] ?? null, |
|
97 | 11 | $route["handler"] ?? null, |
|
98 | 11 | $route["info"] ?? null |
|
99 | ); |
||
100 | 11 | continue; |
|
101 | } |
||
102 | |||
103 | 16 | $mount = $this->createMountPath( |
|
104 | 16 | $routes["mount"] ?? null, |
|
105 | 16 | $route["mount"] ?? null |
|
106 | ); |
||
107 | |||
108 | 16 | $this->addRoute( |
|
109 | 16 | $route["method"] ?? null, |
|
110 | 16 | $mount, |
|
111 | 16 | $route["path"] ?? null, |
|
112 | 16 | $route["handler"] ?? null, |
|
113 | 16 | $route["info"] ?? null |
|
114 | ); |
||
115 | } |
||
116 | |||
117 | 20 | return $this; |
|
118 | } |
||
119 | |||
120 | |||
121 | |||
122 | /** |
||
123 | * Prepare the mount string from configuration, use $mount1 or $mount2, |
||
124 | * the latter supersedes the first. |
||
125 | * |
||
126 | * @param string $mount1 first suggestion to mount path. |
||
127 | * @param string $mount2 second suggestion to mount path, ovverides |
||
128 | * the first. |
||
129 | * |
||
130 | * @return string|null as mount path. |
||
131 | */ |
||
132 | 16 | private function createMountPath( |
|
133 | string $mount1 = null, |
||
134 | string $mount2 = null |
||
135 | ) { |
||
136 | 16 | $mount = null; |
|
137 | 16 | if ($mount1 && $mount2) { |
|
0 ignored issues
–
show
The expression
$mount2 of type null|string is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
Loading history...
|
|||
138 | 13 | $mount = rtrim($mount1, "/") . "/" . rtrim($mount2, "/"); |
|
139 | 13 | return $mount; |
|
140 | } |
||
141 | |||
142 | 15 | if ($mount1) { |
|
0 ignored issues
–
show
The expression
$mount1 of type null|string is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
Loading history...
|
|||
143 | 13 | $mount = $mount1; |
|
144 | } |
||
145 | |||
146 | 15 | if ($mount2) { |
|
0 ignored issues
–
show
The expression
$mount2 of type null|string is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
Loading history...
|
|||
147 | 1 | $mount = $mount2; |
|
148 | } |
||
149 | |||
150 | 15 | trim($mount); |
|
151 | 15 | rtrim($mount, "/"); |
|
152 | 15 | $mount = empty($mount) ? null : $mount; |
|
153 | |||
154 | 15 | return $mount; |
|
155 | } |
||
156 | |||
157 | |||
158 | |||
159 | /** |
||
160 | * Add a route with a request method, a path rule to match and an action |
||
161 | * as the callback. Adding several path rules (array) results in several |
||
162 | * routes being created. |
||
163 | * |
||
164 | * @param string|array $method as request method to support |
||
165 | * @param string $mount prefix to $path |
||
166 | * @param string|array $path for this route, array for several |
||
167 | * paths |
||
168 | * @param string|array|callable $handler for this path, callable or equal |
||
169 | * @param string $info description of the route |
||
170 | * |
||
171 | * @return void. |
||
172 | */ |
||
173 | 105 | public function addRoute( |
|
174 | $method, |
||
175 | $mount = null, |
||
176 | $path = null, |
||
177 | $handler = null, |
||
178 | string $info = null |
||
179 | ) : void { |
||
180 | 105 | if (!is_array($path)) { |
|
181 | 104 | $path = [$path]; |
|
182 | } |
||
183 | |||
184 | 105 | foreach ($path as $thePath) { |
|
185 | 105 | $route = new Route(); |
|
186 | 105 | $route->set($method, $mount, $thePath, $handler, $info); |
|
187 | 105 | $this->routes[] = $route; |
|
188 | } |
||
189 | 105 | } |
|
190 | |||
191 | |||
192 | |||
193 | /** |
||
194 | * Add an internal route to the router, this route is not exposed to the |
||
195 | * browser and the end user. |
||
196 | * |
||
197 | * @param string $path for this route |
||
198 | * @param string|array|callable $handler for this path, callable or equal |
||
199 | * @param string $info description of the route |
||
200 | * |
||
201 | * @return void. |
||
202 | */ |
||
203 | 23 | public function addInternalRoute( |
|
204 | string $path = null, |
||
205 | $handler, |
||
206 | string $info = null |
||
207 | ) : void { |
||
208 | 23 | $route = new Route(); |
|
209 | 23 | $route->set(null, null, $path, $handler, $info); |
|
210 | 23 | $this->internalRoutes[$path] = $route; |
|
211 | 23 | } |
|
212 | |||
213 | |||
214 | |||
215 | /** |
||
216 | * Handle the routes and match them towards the request, dispatch them |
||
217 | * when a match is made. Each route handler may throw exceptions that |
||
218 | * may redirect to an internal route for error handling. |
||
219 | * Several routes can match and if the routehandler does not break |
||
220 | * execution flow, the route matching will carry on. |
||
221 | * Only the last routehandler will get its return value returned further. |
||
222 | * |
||
223 | * @param string $path the path to find a matching handler for. |
||
224 | * @param string $method the request method to match. |
||
225 | * |
||
226 | * @return mixed content returned from route. |
||
227 | */ |
||
228 | 106 | public function handle($path, $method = null) |
|
229 | { |
||
230 | try { |
||
231 | 106 | $match = false; |
|
0 ignored issues
–
show
$match is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
232 | 106 | foreach ($this->routes as $route) { |
|
233 | 105 | if ($route->match($path, $method)) { |
|
234 | 103 | $this->lastRoute = $route; |
|
235 | 103 | $match = true; |
|
0 ignored issues
–
show
$match is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the
Loading history...
|
|||
236 | 103 | $results = $route->handle($path, $this->di); |
|
237 | 89 | if ($results) { |
|
238 | 98 | return $results; |
|
239 | } |
||
240 | } |
||
241 | } |
||
242 | |||
243 | 5 | return $this->handleInternal("404", "No route could be matched by the router."); |
|
244 | 14 | } catch (ForbiddenException $e) { |
|
245 | 3 | return $this->handleInternal("403", $e->getMessage()); |
|
246 | 11 | } catch (NotFoundException $e) { |
|
247 | 2 | return $this->handleInternal("404", $e->getMessage()); |
|
248 | 9 | } catch (InternalErrorException $e) { |
|
249 | 3 | return $this->handleInternal("500", $e->getMessage()); |
|
250 | 6 | } catch (\Exception $e) { |
|
251 | 6 | if ($this->mode === Router::DEVELOPMENT) { |
|
252 | 3 | throw $e; |
|
253 | } |
||
254 | 3 | return $this->handleInternal("500", $e->getMessage()); |
|
255 | } |
||
256 | } |
||
257 | |||
258 | |||
259 | |||
260 | /** |
||
261 | * Handle an internal route, the internal routes are not exposed to the |
||
262 | * end user. |
||
263 | * |
||
264 | * @param string $path for this route. |
||
265 | * @param string $message with additional details. |
||
266 | * |
||
267 | * @throws \Anax\Route\Exception\NotFoundException |
||
268 | * |
||
269 | * @return mixed from the route handler. |
||
270 | */ |
||
271 | 23 | public function handleInternal(string $path, string $message = null) |
|
272 | { |
||
273 | 23 | $route = $this->internalRoutes[$path] |
|
274 | 1 | ?? $this->internalRoutes[null] |
|
275 | 23 | ?? null; |
|
276 | |||
277 | 23 | if (!$route) { |
|
278 | 1 | throw new NotFoundException("No internal route to handle: " . $path); |
|
279 | } |
||
280 | |||
281 | 22 | $this->errorMessage = $message; |
|
282 | 22 | if ($message) { |
|
0 ignored issues
–
show
The expression
$message of type null|string is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
Loading history...
|
|||
283 | 14 | $route->setArguments([$message]); |
|
284 | } |
||
285 | |||
286 | 22 | $route->setMatchedPath($path); |
|
287 | 22 | $this->lastRoute = $route; |
|
288 | 22 | return $route->handle(null, $this->di); |
|
289 | } |
||
290 | |||
291 | |||
292 | |||
293 | /** |
||
294 | * Add a route having a controller as a handler. |
||
295 | * |
||
296 | * @param string|array $mount point for this controller. |
||
297 | * @param string|callable $handler a callback handler for the controller. |
||
298 | * @param string $info description of the route. |
||
299 | * |
||
300 | * @return void. |
||
301 | */ |
||
302 | 1 | public function addController($mount = null, $handler = null, $info = null) |
|
303 | { |
||
304 | 1 | $this->addRoute(null, $mount, null, $handler, $info); |
|
0 ignored issues
–
show
It seems like
$mount defined by parameter $mount on line 302 can also be of type array ; however, Anax\Route\Router::addRoute() does only seem to accept string|null , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
305 | 1 | } |
|
306 | |||
307 | |||
308 | |||
309 | /** |
||
310 | * Add a route to the router by its method(s), path(s) and a callback. |
||
311 | * |
||
312 | * @param string|array $method as request method to support |
||
313 | * @param string|array $path for this route. |
||
314 | * @param string|callable $handler a callback handler for the route. |
||
315 | * @param string $info description of the route |
||
316 | * |
||
317 | * @return void. |
||
318 | */ |
||
319 | 12 | public function any($method = null, $path = null, $handler = null, $info = null) |
|
320 | { |
||
321 | 12 | $this->addRoute($method, null, $path, $handler, $info); |
|
0 ignored issues
–
show
It seems like
$method defined by parameter $method on line 319 can also be of type null ; however, Anax\Route\Router::addRoute() does only seem to accept string|array , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
322 | 12 | } |
|
323 | |||
324 | |||
325 | |||
326 | /** |
||
327 | * Add a route to the router by its path(s) and a callback for any |
||
328 | * request method . |
||
329 | * |
||
330 | * @param string|array $path for this route. |
||
331 | * @param string|callable $handler a callback handler for the route. |
||
332 | * @param string $info description of the route |
||
333 | * |
||
334 | * @return void |
||
335 | */ |
||
336 | 22 | public function add($path = null, $handler = null, $info = null) |
|
337 | { |
||
338 | 22 | $this->addRoute(null, null, $path, $handler, $info); |
|
339 | 22 | } |
|
340 | |||
341 | |||
342 | |||
343 | /** |
||
344 | * Add a default route which will be applied for any path and any |
||
345 | * request method. |
||
346 | * |
||
347 | * @param string|callable $handler a callback handler for the route. |
||
348 | * @param string $info description of the route |
||
349 | * |
||
350 | * @return void |
||
351 | */ |
||
352 | 48 | public function always($handler, $info = null) |
|
353 | { |
||
354 | 48 | $this->addRoute(null, null, null, $handler, $info); |
|
355 | 48 | } |
|
356 | |||
357 | |||
358 | |||
359 | /** |
||
360 | * Add a default route which will be applied for any path, if the choosen |
||
361 | * request method is matching. |
||
362 | * |
||
363 | * @param string|array $method as request method to support |
||
364 | * @param string|callable $handler a callback handler for the route. |
||
365 | * @param string $info description of the route |
||
366 | * |
||
367 | * @return void |
||
368 | */ |
||
369 | 7 | public function all($method, $handler, $info = null) |
|
370 | { |
||
371 | 7 | $this->addRoute($method, null, null, $handler, $info); |
|
372 | 7 | } |
|
373 | |||
374 | |||
375 | |||
376 | /** |
||
377 | * Shortcut to add a GET route for the http request method GET. |
||
378 | * |
||
379 | * @param string|array $path for this route. |
||
380 | * @param string|callable $handler a callback handler for the route. |
||
381 | * @param string $info description of the route |
||
382 | * |
||
383 | * @return void |
||
384 | */ |
||
385 | 6 | public function get($path, $handler, $info = null) |
|
386 | { |
||
387 | 6 | $this->addRoute(["GET"], null, $path, $handler, $info); |
|
388 | 6 | } |
|
389 | |||
390 | |||
391 | |||
392 | /** |
||
393 | * Shortcut to add a POST route for the http request method POST. |
||
394 | * |
||
395 | * @param string|array $path for this route. |
||
396 | * @param string|callable $handler a callback handler for the route. |
||
397 | * @param string $info description of the route |
||
398 | * |
||
399 | * @return void |
||
400 | */ |
||
401 | 6 | public function post($path, $handler, $info = null) |
|
402 | { |
||
403 | 6 | $this->addRoute(["POST"], null, $path, $handler, $info); |
|
404 | 6 | } |
|
405 | |||
406 | |||
407 | |||
408 | /** |
||
409 | * Shortcut to add a PUT route for the http request method PUT. |
||
410 | * |
||
411 | * @param string|array $path for this route. |
||
412 | * @param string|callable $handler a callback handler for the route. |
||
413 | * @param string $info description of the route |
||
414 | * |
||
415 | * @return void |
||
416 | */ |
||
417 | 6 | public function put($path, $handler, $info = null) |
|
418 | { |
||
419 | 6 | $this->addRoute(["PUT"], null, $path, $handler, $info); |
|
420 | 6 | } |
|
421 | |||
422 | |||
423 | |||
424 | /** |
||
425 | * Shortcut to add a PATCH route for the http request method PATCH. |
||
426 | * |
||
427 | * @param string|array $path for this route. |
||
428 | * @param string|callable $handler a callback handler for the route. |
||
429 | * @param string $info description of the route |
||
430 | * |
||
431 | * @return void |
||
432 | */ |
||
433 | 6 | public function patch($path, $handler, $info = null) |
|
434 | { |
||
435 | 6 | $this->addRoute(["PATCH"], null, $path, $handler, $info); |
|
436 | 6 | } |
|
437 | |||
438 | |||
439 | |||
440 | /** |
||
441 | * Shortcut to add a DELETE route for the http request method DELETE. |
||
442 | * |
||
443 | * @param string|array $path for this route. |
||
444 | * @param string|callable $handler a callback handler for the route. |
||
445 | * @param string $info description of the route |
||
446 | * |
||
447 | * @return void |
||
448 | */ |
||
449 | 6 | public function delete($path, $handler, $info = null) |
|
450 | { |
||
451 | 6 | $this->addRoute(["DELETE"], null, $path, $handler, $info); |
|
452 | 6 | } |
|
453 | |||
454 | |||
455 | |||
456 | /** |
||
457 | * Shortcut to add a OPTIONS route for the http request method OPTIONS. |
||
458 | * |
||
459 | * @param string|array $path for this route. |
||
460 | * @param string|callable $handler a callback handler for the route. |
||
461 | * @param string $info description of the route |
||
462 | * |
||
463 | * @return void |
||
464 | */ |
||
465 | 6 | public function options($path, $handler, $info = null) |
|
466 | { |
||
467 | 6 | $this->addRoute(["OPTIONS"], null, $path, $handler, $info); |
|
468 | 6 | } |
|
469 | |||
470 | |||
471 | |||
472 | /** |
||
473 | * Get the route for the last route that was handled. |
||
474 | * |
||
475 | * @return mixed |
||
476 | */ |
||
477 | 4 | public function getLastRoute() |
|
478 | { |
||
479 | 4 | return $this->lastRoute->getAbsolutePath(); |
|
480 | } |
||
481 | |||
482 | |||
483 | |||
484 | /** |
||
485 | * Get the route for the last route that was handled. |
||
486 | * |
||
487 | * @return mixed |
||
488 | */ |
||
489 | 3 | public function getMatchedPath() |
|
490 | { |
||
491 | 3 | return $this->lastRoute->getMatchedPath(); |
|
492 | } |
||
493 | |||
494 | |||
495 | |||
496 | /** |
||
497 | * Get last error message supplied when handling internal routes. |
||
498 | * |
||
499 | * @return string as the error message, if any. |
||
500 | */ |
||
501 | 1 | public function getErrorMessage() : ?string |
|
502 | { |
||
503 | 1 | return $this->errorMessage; |
|
504 | } |
||
505 | |||
506 | |||
507 | |||
508 | /** |
||
509 | * Get all routes. |
||
510 | * |
||
511 | * @return array with all routes. |
||
512 | */ |
||
513 | 74 | public function getAll() |
|
514 | { |
||
515 | 74 | return $this->routes; |
|
516 | } |
||
517 | |||
518 | |||
519 | |||
520 | /** |
||
521 | * Get all internal routes. |
||
522 | * |
||
523 | * @return array with internal routes. |
||
524 | */ |
||
525 | 5 | public function getInternal() |
|
526 | { |
||
527 | 5 | return $this->internalRoutes; |
|
528 | } |
||
529 | } |
||
530 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: