1515use Psr \Http \Message \ServerRequestInterface ;
1616
1717/**
18+ * Constructeur CORS (Cross-Origin Resource Sharing)
19+ *
20+ * Cette classe gère la configuration et l'application des en-têtes CORS
21+ * pour les requêtes cross-origin selon les spécifications W3C.
22+ *
1823 * @credit CodeIgniter4 Cors <a href="https://github.com/agungsugiarto/codeigniter4-cors">Fluent\Cors\ServiceCors</a>
1924 */
2025class CorsBuilder
2126{
27+ /**
28+ * Options de configuration CORS
29+ */
2230 protected array $ options = [];
2331
32+ /**
33+ * Constructeur de la classe CorsBuilder
34+ *
35+ * @param array $options Options de configuration CORS
36+ */
2437 public function __construct (array $ options = [])
2538 {
2639 $ this ->options = $ this ->normalizeOptions ($ options );
2740 }
2841
42+ /**
43+ * Normalise les options de configuration CORS
44+ */
2945 protected function normalizeOptions (array $ options = []): array
3046 {
3147 $ options = array_merge ([
@@ -38,10 +54,10 @@ protected function normalizeOptions(array $options = []): array
3854 'maxAge ' => 0 ,
3955 ], $ options );
4056
41- // Normaliser la casse
57+ // Normaliser la casse des méthodes
4258 $ options ['allowedMethods ' ] = array_map ('strtoupper ' , $ options ['allowedMethods ' ]);
4359
44- // normalizer ['*'] en true
60+ // Normaliser ['*'] en true pour les origines, en-têtes et méthodes
4561 if (in_array ('* ' , $ options ['allowedOrigins ' ], true )) {
4662 $ options ['allowedOrigins ' ] = true ;
4763 }
@@ -55,16 +71,39 @@ protected function normalizeOptions(array $options = []): array
5571 return $ options ;
5672 }
5773
74+ /**
75+ * Vérifie si la requête est une requête CORS
76+ *
77+ * Une requête est considérée comme CORS si elle contient un en-tête Origin
78+ * et que l'origine est différente de l'hôte du serveur
79+ *
80+ * @return bool true si c'est une requête CORS, false sinon
81+ */
5882 public function isCorsRequest (ServerRequestInterface $ request ): bool
5983 {
6084 return $ request ->hasHeader ('Origin ' ) && ! $ this ->isSameHost ($ request );
6185 }
6286
87+ /**
88+ * Vérifie si la requête est une requête préflight (OPTIONS)
89+ *
90+ * Une requête préflight est une requête OPTIONS envoyée par le navigateur
91+ * pour vérifier si la requête CORS est autorisée
92+ *
93+ * @return bool true si c'est une requête préflight, false sinon
94+ */
6395 public function isPreflightRequest (ServerRequestInterface $ request ): bool
6496 {
6597 return strtoupper ($ request ->getMethod ()) === 'OPTIONS ' && $ request ->hasHeader ('Access-Control-Request-Method ' );
6698 }
6799
100+ /**
101+ * Traite une requête préflight et retourne une réponse appropriée
102+ *
103+ * @param ServerRequestInterface $request Requête préflight
104+ *
105+ * @return ResponseInterface Réponse avec les en-têtes CORS appropriés
106+ */
68107 public function handlePreflightRequest (ServerRequestInterface $ request ): ResponseInterface
69108 {
70109 $ response = new Response ();
@@ -74,6 +113,14 @@ public function handlePreflightRequest(ServerRequestInterface $request): Respons
74113 return $ this ->addPreflightRequestHeaders ($ request , $ response );
75114 }
76115
116+ /**
117+ * Ajoute les en-têtes appropriés pour une réponse à une requête préflight
118+ *
119+ * @param ServerRequestInterface $request Requête préflight
120+ * @param ResponseInterface $response Réponse à modifier
121+ *
122+ * @return ResponseInterface Réponse avec les en-têtes CORS ajoutés
123+ */
77124 public function addPreflightRequestHeaders (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
78125 {
79126 $ response = $ this ->configureAllowedOrigin ($ request , $ response );
@@ -88,6 +135,11 @@ public function addPreflightRequestHeaders(ServerRequestInterface $request, Resp
88135 return $ response ;
89136 }
90137
138+ /**
139+ * Vérifie si l'origine de la requête est autorisée
140+ *
141+ * @return bool true si l'origine est autorisée, false sinon
142+ */
91143 public function isOriginAllowed (ServerRequestInterface $ request ): bool
92144 {
93145 if ($ this ->options ['allowedOrigins ' ] === true ) {
@@ -113,6 +165,14 @@ public function isOriginAllowed(ServerRequestInterface $request): bool
113165 return false ;
114166 }
115167
168+ /**
169+ * Ajoute les en-têtes CORS appropriés pour une requête actuelle (non préflight)
170+ *
171+ * @param ServerRequestInterface $request Requête actuelle
172+ * @param ResponseInterface $response Réponse à modifier
173+ *
174+ * @return ResponseInterface Réponse avec les en-têtes CORS ajoutés
175+ */
116176 public function addActualRequestHeaders (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
117177 {
118178 $ response = $ this ->configureAllowedOrigin ($ request , $ response );
@@ -125,6 +185,17 @@ public function addActualRequestHeaders(ServerRequestInterface $request, Respons
125185 return $ response ;
126186 }
127187
188+ /**
189+ * Ajoute un en-tête à l'en-tête Vary de la réponse
190+ *
191+ * L'en-tête Vary indique au cache quelles parties de la requête
192+ * peuvent affecter la réponse
193+ *
194+ * @param ResponseInterface $response Réponse à modifier
195+ * @param string $header En-tête à ajouter à Vary
196+ *
197+ * @return ResponseInterface Réponse avec l'en-tête Vary mis à jour
198+ */
128199 public function varyHeader (ResponseInterface $ response , $ header ): ResponseInterface
129200 {
130201 if (! $ response ->hasHeader ('Vary ' )) {
@@ -136,16 +207,24 @@ public function varyHeader(ResponseInterface $response, $header): ResponseInterf
136207 return $ response ;
137208 }
138209
210+ /**
211+ * Configure l'en-tête Access-Control-Allow-Origin
212+ *
213+ * @param ServerRequestInterface $request Requête courante
214+ * @param ResponseInterface $response Réponse à modifier
215+ *
216+ * @return ResponseInterface Réponse avec l'en-tête Access-Control-Allow-Origin configuré
217+ */
139218 protected function configureAllowedOrigin (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
140219 {
141220 if ($ this ->options ['allowedOrigins ' ] === true && ! $ this ->options ['supportsCredentials ' ]) {
142- // Sûr+cacheable, tout autoriser
221+ // Sûr et pouvant être mis en cache, autoriser toutes les origines
143222 $ response = $ response ->withHeader ('Access-Control-Allow-Origin ' , '* ' );
144223 } elseif ($ this ->isSingleOriginAllowed ()) {
145224 // Les origines uniques peuvent être définies en toute sécurité
146225 $ response = $ response ->withHeader ('Access-Control-Allow-Origin ' , array_values ($ this ->options ['allowedOrigins ' ])[0 ]);
147226 } else {
148- // Pour les en-têtes dynamiques, définir l'en-tête Origin demandé lorsqu' il est défini et autorisé.
227+ // Pour les en-têtes dynamiques, définir l'en-tête Origin demandé quand il est défini et autorisé
149228 if ($ this ->isCorsRequest ($ request ) && $ this ->isOriginAllowed ($ request )) {
150229 $ response = $ response ->withHeader ('Access-Control-Allow-Origin ' , $ request ->getHeaderLine ('Origin ' ));
151230 }
@@ -156,6 +235,11 @@ protected function configureAllowedOrigin(ServerRequestInterface $request, Respo
156235 return $ response ;
157236 }
158237
238+ /**
239+ * Vérifie si une seule origine est autorisée
240+ *
241+ * @return bool true si une seule origine est autorisée, false sinon
242+ */
159243 protected function isSingleOriginAllowed (): bool
160244 {
161245 if ($ this ->options ['allowedOrigins ' ] === true || ! empty ($ this ->options ['allowedOriginsPatterns ' ])) {
@@ -165,6 +249,14 @@ protected function isSingleOriginAllowed(): bool
165249 return count ($ this ->options ['allowedOrigins ' ]) === 1 ;
166250 }
167251
252+ /**
253+ * Configure l'en-tête Access-Control-Allow-Methods
254+ *
255+ * @param ServerRequestInterface $request Requête courante
256+ * @param ResponseInterface $response Réponse à modifier
257+ *
258+ * @return ResponseInterface Réponse avec l'en-tête Access-Control-Allow-Methods configuré
259+ */
168260 protected function configureAllowedMethods (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
169261 {
170262 if ($ this ->options ['allowedMethods ' ] === true ) {
@@ -177,6 +269,14 @@ protected function configureAllowedMethods(ServerRequestInterface $request, Resp
177269 return $ response ->withHeader ('Access-Control-Allow-Methods ' , $ allowMethods );
178270 }
179271
272+ /**
273+ * Configure l'en-tête Access-Control-Allow-Headers
274+ *
275+ * @param ServerRequestInterface $request Requête courante
276+ * @param ResponseInterface $response Réponse à modifier
277+ *
278+ * @return ResponseInterface Réponse avec l'en-tête Access-Control-Allow-Headers configuré
279+ */
180280 protected function configureAllowedHeaders (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
181281 {
182282 if ($ this ->options ['allowedHeaders ' ] === true ) {
@@ -189,6 +289,14 @@ protected function configureAllowedHeaders(ServerRequestInterface $request, Resp
189289 return $ response ->withHeader ('Access-Control-Allow-Headers ' , $ allowHeaders );
190290 }
191291
292+ /**
293+ * Configure l'en-tête Access-Control-Allow-Credentials
294+ *
295+ * @param ServerRequestInterface $request Requête courante
296+ * @param ResponseInterface $response Réponse à modifier
297+ *
298+ * @return ResponseInterface Réponse avec l'en-tête Access-Control-Allow-Credentials configuré
299+ */
192300 protected function configureAllowCredentials (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
193301 {
194302 if ($ this ->options ['supportsCredentials ' ]) {
@@ -198,6 +306,14 @@ protected function configureAllowCredentials(ServerRequestInterface $request, Re
198306 return $ response ;
199307 }
200308
309+ /**
310+ * Configure l'en-tête Access-Control-Expose-Headers
311+ *
312+ * @param ServerRequestInterface $request Requête courante
313+ * @param ResponseInterface $response Réponse à modifier
314+ *
315+ * @return ResponseInterface Réponse avec l'en-tête Access-Control-Expose-Headers configuré
316+ */
201317 protected function configureExposedHeaders (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
202318 {
203319 if ($ this ->options ['exposedHeaders ' ]) {
@@ -207,6 +323,14 @@ protected function configureExposedHeaders(ServerRequestInterface $request, Resp
207323 return $ response ;
208324 }
209325
326+ /**
327+ * Configure l'en-tête Access-Control-Max-Age
328+ *
329+ * @param ServerRequestInterface $request Requête courante
330+ * @param ResponseInterface $response Réponse à modifier
331+ *
332+ * @return ResponseInterface Réponse avec l'en-tête Access-Control-Max-Age configuré
333+ */
210334 protected function configureMaxAge (ServerRequestInterface $ request , ResponseInterface $ response ): ResponseInterface
211335 {
212336 if ($ this ->options ['maxAge ' ] !== null ) {
@@ -216,6 +340,11 @@ protected function configureMaxAge(ServerRequestInterface $request, ResponseInte
216340 return $ response ;
217341 }
218342
343+ /**
344+ * Vérifie si la requête provient du même hôte
345+ *
346+ * @return bool true si la requête provient du même hôte, false sinon
347+ */
219348 protected function isSameHost (ServerRequestInterface $ request ): bool
220349 {
221350 return $ request ->getHeaderLine ('Origin ' ) === config ('app.base_url ' );
0 commit comments