This repository was archived by the owner on Jun 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathBaseRouter.php
More file actions
106 lines (91 loc) · 2.88 KB
/
Copy pathBaseRouter.php
File metadata and controls
106 lines (91 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?hh // strict
/*
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
namespace Facebook\HackRouter;
use namespace HH\Lib\{C, Dict};
use function Facebook\AutoloadMap\Generated\is_dev;
abstract class BaseRouter<+TResponder> {
abstract protected function getRoutes(
): KeyedContainer<HttpMethod, KeyedContainer<string, TResponder>>;
final public function routeMethodAndPath(
HttpMethod $method,
string $path,
): (TResponder, dict<string, string>) {
$resolver = $this->getResolver();
try {
list($responder, $data) = $resolver->resolve($method, $path);
$data = Dict\map($data, $value ==> \urldecode($value));
return tuple($responder, $data);
} catch (NotFoundException $e) {
$allowed = $this->getAllowedMethods($path);
if (C\is_empty($allowed)) {
throw $e;
}
if (
$method === HttpMethod::HEAD && $allowed === keyset[HttpMethod::GET]
) {
list($responder, $data) = $resolver->resolve(HttpMethod::GET, $path);
$data = Dict\map($data, $value ==> \urldecode($value));
return tuple($responder, $data);
}
throw new MethodNotAllowedException($allowed);
}
}
final public function routeRequest(
\Facebook\Experimental\Http\Message\RequestInterface $request,
): (TResponder, dict<string, string>) {
$method = HttpMethod::coerce($request->getMethod());
if ($method === null) {
throw new MethodNotAllowedException(
$this->getAllowedMethods($request->getUri()->getPath()),
);
}
return $this->routeMethodAndPath($method, $request->getUri()->getPath());
}
private function getAllowedMethods(string $path): keyset<HttpMethod> {
$resolver = $this->getResolver();
$allowed = keyset[];
foreach (HttpMethod::getValues() as $method) {
try {
list($_responder, $_data) = $resolver->resolve($method, $path);
$allowed[] = $method;
} catch (NotFoundException $_) {
continue;
}
}
return $allowed;
}
private ?IResolver<TResponder> $resolver = null;
protected function getResolver(): IResolver<TResponder> {
if ($this->resolver !== null) {
return $this->resolver;
}
if (is_dev()) {
$routes = null;
} else {
$_success = null;
$routes = \apc_fetch(__FILE__.'/cache', inout $_success);
if ($routes === false) {
$routes = null;
}
}
if ($routes === null) {
$routes = Dict\map(
$this->getRoutes(),
$method_routes ==>
PrefixMatching\PrefixMap::fromFlatMap(dict($method_routes)),
);
if (!is_dev()) {
\apc_store(__FILE__.'/cache', $routes);
}
}
$this->resolver = new PrefixMatchingResolver($routes);
return $this->resolver;
}
}