Passed
Push — main ( 66245a...80ccfb )
by Dimitri
12:45 queued 12s
created

Cors::process()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 3
eloc 13
c 2
b 1
f 0
nc 3
nop 2
dl 0
loc 20
rs 9.8333
1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace BlitzPHP\Middlewares;
13
14
use Psr\Http\Message\ResponseInterface;
15
use Psr\Http\Message\ServerRequestInterface;
16
use Psr\Http\Server\MiddlewareInterface;
17
use Psr\Http\Server\RequestHandlerInterface;
18
19
/**
20
 * Cors
21
 *  Middleware cors pour gerer les requetes d'origine croisees
22
 */
23
class Cors implements MiddlewareInterface
24
{
25
    protected $config = [
26
        'AllowOrigin'      => true,
27
        'AllowCredentials' => true,
28
        'AllowMethods'     => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
29
        'AllowHeaders'     => true,
30
        'ExposeHeaders'    => false,
31
        'MaxAge'           => 86400,                                       // 1 day
32
    ];
33
34
    /**
35
     * Constructor
36
     */
37
    public function __construct(array $config = [])
38
    {
39
        $this->config = array_merge($this->config, $config);
40
    }
41
42
    /**
43
     * Modifie le MaxAge
44
     *
45
     * @param float|int $maxAge
46
     */
47
    public function setMaxAge($maxAge): self
48
    {
49
        $this->config['MaxAge'] = $maxAge;
50
51
        return $this;
52
    }
53
54
    /**
55
     * Modifie les entetes exposes
56
     *
57
     * @param bool|string|string[] $exposeHeaders
58
     */
59
    public function setExposeHeaders($exposeHeaders): self
60
    {
61
        $this->config['ExposeHeaders'] = $exposeHeaders;
62
63
        return $this;
64
    }
65
66
    /**
67
     * Modifie les entetes autorises
68
     *
69
     * @param bool|string|string[] $headers
70
     */
71
    public function setHeaders($headers): self
72
    {
73
        $this->config['AllowHeaders'] = $headers;
74
75
        return $this;
76
    }
77
78
    /**
79
     * Modifie les methodes autorisees
80
     *
81
     * @param string|string[] $methods
82
     */
83
    public function setMethods($methods): self
84
    {
85
        $this->config['AlloMethods'] = $methods;
86
87
        return $this;
88
    }
89
90
    /**
91
     * Defini si on doit utiliser les informations d'identifications ou pas
92
     */
93
    public function setCredentials(bool $credentials): self
94
    {
95
        $this->config['AllowCredentials'] = $credentials;
96
97
        return $this;
98
    }
99
100
    /**
101
     * Modifie les origines autorisees
102
     *
103
     * @param bool|string|string[] $origin
104
     */
105
    public function setOrigin($origin): self
106
    {
107
        $this->config['AllowOrigin'] = $origin;
108
109
        return $this;
110
    }
111
112
    /**
113
     * Execution du middleware
114
     */
115
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
116
    {
117
        $response = $handler->handle($request);
118
119
        if ($request->getHeaderLine('Origin')) {
120
            $response = $response
121
                ->withHeader('Access-Control-Allow-Origin', $this->_allowOrigin($request))
122
                ->withHeader('Access-Control-Allow-Credentials', $this->_allowCredentials())
123
                ->withHeader('Access-Control-Max-Age', $this->_maxAge())
124
                ->withHeader('Access-Control-Expose-Headers', $this->_exposeHeaders());
125
126
            if (strtoupper($request->getMethod()) === 'OPTIONS') {
127
                $response = $response
128
                    ->withHeader('Access-Control-Allow-Headers', $this->_allowHeaders($request))
129
                    ->withHeader('Access-Control-Allow-Methods', $this->_allowMethods())
130
                    ->withStatus(200);
131
            }
132
        }
133
134
        return $response;
135
    }
136
137
    /**
138
     * Recupere les origines autorisees
139
     */
140
    private function _allowOrigin(ServerRequestInterface $request)
141
    {
142
        $allowOrigin = $this->config['AllowOrigin'];
143
        $origin      = $request->getHeaderLine('Origin');
144
145
        if ($allowOrigin === true || $allowOrigin === '*') {
146
            return $origin;
147
        }
148
149
        if (is_array($allowOrigin)) {
150
            $origin = (array) $origin;
151
152
            foreach ($origin as $o) {
153
                if (in_array($o, $allowOrigin, true)) {
154
                    return $origin;
155
                }
156
            }
157
158
            return '';
159
        }
160
161
        return (string) $allowOrigin;
162
    }
163
164
    /**
165
     * Autorise t-on les identifications ?
166
     */
167
    private function _allowCredentials(): string
168
    {
169
        return ($this->config['AllowCredentials']) ? 'true' : 'false';
170
    }
171
172
    /**
173
     * Recupere les methodes autorisees
174
     */
175
    private function _allowMethods(): string
176
    {
177
        return implode(', ', (array) $this->config['AllowMethods']);
178
    }
179
180
    /**
181
     * Recupere les entetes autorises
182
     */
183
    private function _allowHeaders(ServerRequestInterface $request): string
184
    {
185
        $allowHeaders = $this->config['AllowHeaders'];
186
187
        if ($allowHeaders === true) {
188
            return $request->getHeaderLine('Access-Control-Request-Headers');
189
        }
190
191
        return implode(', ', (array) $allowHeaders);
192
    }
193
194
    /**
195
     * Recupere les entetes exposes par l'application
196
     */
197
    private function _exposeHeaders(): string
198
    {
199
        $exposeHeaders = $this->config['ExposeHeaders'];
200
201
        if (is_string($exposeHeaders) || is_array($exposeHeaders)) {
202
            return implode(', ', (array) $exposeHeaders);
203
        }
204
205
        return '';
206
    }
207
208
    /**
209
     * Recupere la duree de mise en cache des donnees
210
     */
211
    private function _maxAge(): string
212
    {
213
        $maxAge = (string) $this->config['MaxAge'];
214
215
        return ($maxAge) ?: '0';
216
    }
217
}
218