1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace BenTools\MercurePHP\Security; |
4
|
|
|
|
5
|
|
|
use BenTools\MercurePHP\Configuration\Configuration; |
6
|
|
|
use Psr\Http\Message\ResponseInterface; |
7
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
8
|
|
|
|
9
|
|
|
use function BenTools\MercurePHP\nullify; |
10
|
|
|
|
11
|
|
|
final class CORS |
12
|
|
|
{ |
13
|
|
|
private array $subscriberConfig; |
14
|
361 |
|
private array $publisherConfig; |
15
|
|
|
|
16
|
361 |
|
public function __construct(array $config) |
17
|
361 |
|
{ |
18
|
361 |
|
$this->subscriberConfig = ['origins' => self::normalizeAllowedOrigins($config[Configuration::CORS_ALLOWED_ORIGINS])]; |
19
|
361 |
|
$this->publisherConfig = ['origins' => self::normalizeAllowedOrigins($config[Configuration::PUBLISH_ALLOWED_ORIGINS])]; |
20
|
361 |
|
$this->subscriberConfig['all'] = self::allowsAllOrigins($this->subscriberConfig['origins']); |
21
|
|
|
$this->publisherConfig['all'] = self::allowsAllOrigins($this->publisherConfig['origins']); |
22
|
364 |
|
} |
23
|
|
|
|
24
|
364 |
|
public function decorateResponse(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface |
25
|
364 |
|
{ |
26
|
132 |
|
$headers = $this->getCorsHeaders($request); |
27
|
|
|
foreach ($headers as $key => $value) { |
28
|
|
|
$response = $response->withHeader($key, $value); |
29
|
364 |
|
} |
30
|
|
|
|
31
|
|
|
return $response; |
32
|
364 |
|
} |
33
|
|
|
|
34
|
364 |
|
private function getCorsHeaders(ServerRequestInterface $request): array |
35
|
364 |
|
{ |
36
|
76 |
|
$origin = nullify($request->getHeaderLine('Origin')) ?? nullify($request->getHeaderLine('Referer')); |
37
|
|
|
if (!$origin) { |
38
|
|
|
return []; |
39
|
288 |
|
} |
40
|
|
|
|
41
|
288 |
|
$config = 'POST' === $request->getMethod() ? $this->publisherConfig : $this->subscriberConfig; |
42
|
156 |
|
|
43
|
|
|
if (!$config['all'] && !\in_array($origin, $config['origins'], true)) { |
44
|
|
|
return []; |
45
|
|
|
} |
46
|
132 |
|
|
47
|
132 |
|
return [ |
48
|
132 |
|
'Access-Control-Allow-Origin' => $origin, |
49
|
132 |
|
'Access-Control-Allow-Credentials' => 'true', |
50
|
132 |
|
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS', |
51
|
|
|
'Access-Control-Allow-Headers' => 'Cache-control, Authorization, Last-Event-ID', |
52
|
|
|
'Access-Control-Max-Age' => 3600, |
53
|
|
|
]; |
54
|
361 |
|
} |
55
|
|
|
|
56
|
361 |
|
private static function normalizeAllowedOrigins(string $allowedOrigins): array |
57
|
|
|
{ |
58
|
361 |
|
$allowedOrigins = \strtr($allowedOrigins, [';' => ' ', ',' => ' ']); |
59
|
|
|
|
60
|
|
|
return \array_map('\\trim', \explode(' ', $allowedOrigins)); |
61
|
361 |
|
} |
62
|
|
|
|
63
|
361 |
|
private static function allowsAllOrigins(array $origins): bool |
64
|
|
|
{ |
65
|
|
|
return \in_array('*', $origins, true); |
66
|
|
|
} |
67
|
|
|
} |
68
|
|
|
|