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