Passed
Push — master ( bb88eb...972d9a )
by Dominik
01:47
created

CorsMiddleware::process()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 11
cts 11
cp 1
rs 9.7
c 0
b 0
f 0
cc 4
nc 2
nop 2
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\Cors;
6
7
use Psr\Http\Message\ResponseFactoryInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use Psr\Http\Server\MiddlewareInterface;
11
use Psr\Http\Server\RequestHandlerInterface;
12
13
final class CorsMiddleware implements MiddlewareInterface
14
{
15
    /**
16
     * @var ResponseFactoryInterface
17
     */
18
    private $responseFactory;
19
20
    /**
21
     * @var string[]
22
     */
23
    private $allowOrigin;
24
25
    /**
26
     * @var string[]
27
     */
28
    private $allowMethods;
29
30
    /**
31
     * @var string[]
32
     */
33
    private $allowHeaders;
34
35
    /**
36
     * @var bool
37
     */
38
    private $allowCredentials;
39
40
    /**
41
     * @var int
42
     */
43
    private $maxAge;
44
45
    /**
46
     * @param ResponseFactoryInterface $responseFactory
47
     * @param string[]                 $allowHeaders
48
     * @param string[]                 $allowMethods
49
     * @param string[]                 $allowOrigin
50
     * @param bool                     $allowCredentials
51
     * @param int                      $maxAge
52
     */
53 6
    public function __construct(
54
        ResponseFactoryInterface $responseFactory,
55
        array $allowOrigin,
56
        array $allowMethods,
57
        array $allowHeaders,
58
        bool $allowCredentials = false,
59
        int $maxAge = 600
60
    ) {
61 6
        $this->responseFactory = $responseFactory;
62 6
        $this->allowOrigin = $allowOrigin;
63 6
        $this->allowMethods = $allowMethods;
64 6
        $this->allowHeaders = $allowHeaders;
65 6
        $this->allowCredentials = $allowCredentials;
66 6
        $this->maxAge = $maxAge;
67 6
    }
68
69
    /**
70
     * @param ServerRequestInterface  $request
71
     * @param RequestHandlerInterface $handler
72
     *
73
     * @return ResponseInterface
74
     */
75 6
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
76
    {
77 6
        if ('OPTIONS' === strtoupper($request->getMethod())) {
78 3
            return $this->responseFactory->createResponse(204)
79 3
                ->withHeader('Access-Control-Allow-Origin', $this->getAllowOrigin($request))
80 3
                ->withHeader('Access-Control-Allow-Methods', implode(', ', $this->allowMethods))
81 3
                ->withHeader('Access-Control-Allow-Headers', implode(', ', $this->allowHeaders))
82 3
                ->withHeader('Access-Control-Allow-Credentials', $this->allowCredentials ? 'true' : 'false')
83 3
                ->withHeader('Access-Control-Max-Age', (string) $this->maxAge)
84
            ;
85
        }
86
87 3
        return $handler->handle($request)
88 3
            ->withHeader('Access-Control-Allow-Origin', $this->getAllowOrigin($request))
89 3
            ->withHeader('Access-Control-Allow-Credentials', $this->allowCredentials ? 'true' : 'false')
90
        ;
91
    }
92
93
    /**
94
     * @param ServerRequestInterface $request
95
     *
96
     * @return string
97
     */
98 6
    private function getAllowOrigin(ServerRequestInterface $request): string
99
    {
100 6
        if ('' === $origin = $request->getHeaderLine('Origin')) {
101 1
            return '';
102
        }
103
104 5
        foreach ($this->allowOrigin as $allowOrigin) {
105 5
            if ('~' === $allowOrigin[0] ?? '') {
106 2
                if (1 === preg_match('!'.substr($allowOrigin, 1).'!', $origin)) {
107 2
                    return $origin;
108
                }
109
            } else {
110 3
                if ($allowOrigin === $origin) {
111 4
                    return $origin;
112
                }
113
            }
114
        }
115
116 2
        return '';
117
    }
118
}
119