1 | <?php |
||
9 | class Cors |
||
10 | { |
||
11 | private $options; |
||
12 | |||
13 | 38 | public function __construct($options = []) |
|
17 | |||
18 | 34 | public function __invoke(Request $request, Response $response, Application $app) |
|
19 | { |
||
20 | $defaults = [ |
||
21 | 34 | "allowOrigin" => $app["cors.allowOrigin"], |
|
22 | 34 | "allowMethods" => $app["cors.allowMethods"], |
|
23 | 34 | "allowHeaders" => $app["cors.allowHeaders"], |
|
24 | 34 | "maxAge" => $app["cors.maxAge"], |
|
25 | 34 | "allowCredentials" => $app["cors.allowCredentials"], |
|
26 | 34 | "exposeHeaders" => $app["cors.exposeHeaders"] |
|
27 | ]; |
||
28 | 34 | $this->cors($request, $response, $this->options + $defaults); |
|
29 | 34 | } |
|
30 | |||
31 | 34 | private function cors(Request $request, Response $response, $options) |
|
32 | { |
||
33 | 34 | $headers = []; |
|
34 | |||
35 | 34 | if (!$this->isCorsRequest($request)) { |
|
36 | 2 | return []; |
|
37 | } |
||
38 | |||
39 | 32 | if ($this->isPreflightRequest($request)) { |
|
40 | 16 | $requestMethod = $request->headers->get("Access-Control-Request-Method"); |
|
41 | 16 | $allow = $response->headers->get("Allow"); |
|
42 | 16 | if (!$this->isMethodAllowed($requestMethod, $allow, $options["allowMethods"])) { |
|
43 | 2 | return []; |
|
44 | } |
||
45 | |||
46 | 14 | $requestHeaders = $request->headers->get("Access-Control-Request-Headers"); |
|
47 | 14 | if (!$this->areHeadersAllowed($requestHeaders, $options["allowHeaders"])) { |
|
48 | 1 | return []; |
|
49 | } |
||
50 | |||
51 | 13 | $headers["Access-Control-Allow-Headers"] = $requestHeaders; |
|
52 | 13 | $headers["Access-Control-Allow-Methods"] = $requestMethod; |
|
53 | 13 | $headers["Access-Control-Max-Age"] = $options["maxAge"]; |
|
54 | } else { |
||
55 | 16 | $headers["Access-Control-Expose-Headers"] = $options["exposeHeaders"]; |
|
56 | } |
||
57 | |||
58 | 29 | $allowOrigin = $this->allowOrigin($request, $options["allowOrigin"]); |
|
59 | |||
60 | 29 | if (!$allowOrigin) { |
|
61 | 9 | return []; |
|
62 | } |
||
63 | |||
64 | 20 | $headers["Access-Control-Allow-Origin"] = $allowOrigin; |
|
65 | 20 | $headers["Access-Control-Allow-Credentials"] = $this->allowCredentials($options["allowCredentials"]); |
|
66 | |||
67 | 20 | $response->headers->add(array_filter($headers)); |
|
68 | 20 | } |
|
69 | |||
70 | 34 | private function isCorsRequest(Request $request) |
|
74 | |||
75 | 32 | private function isPreflightRequest(Request $request) |
|
79 | |||
80 | 16 | private function isMethodAllowed($requestMethod, $allow, $allowMethods) |
|
86 | |||
87 | 14 | private function areHeadersAllowed($commaSeparatedRequestHeaders, $allowHeaders) |
|
96 | |||
97 | 29 | private function allowOrigin(Request $request, $allowOrigin) |
|
98 | { |
||
99 | 29 | $origin = $request->headers->get("Origin"); |
|
100 | 29 | if ($allowOrigin === "*") { |
|
101 | 14 | $allowOrigin = $origin; |
|
102 | } |
||
103 | |||
104 | 29 | $origins = array_filter(preg_split('/\s+/', $allowOrigin)); |
|
105 | 29 | foreach ($origins as $domain) { |
|
106 | 29 | if (preg_match($this->domainToRegex($domain), $origin)) { |
|
107 | 29 | return $origin; |
|
108 | } |
||
109 | } |
||
110 | |||
111 | 9 | return false; |
|
112 | } |
||
113 | |||
114 | 29 | private function domainToRegex($domain) |
|
124 | |||
125 | 29 | private function doubleQuote($subject) |
|
129 | |||
130 | 20 | private function allowCredentials($allowCredentials) |
|
134 | } |
||
135 |