add CORS manager with relative docs

This commit is contained in:
2026-07-16 15:18:24 +02:00
parent ec26db0bfa
commit 85843e99c7
6 changed files with 373 additions and 1 deletions
+112
View File
@@ -0,0 +1,112 @@
<?php
namespace Api\Core;
class CorsManager {
private $allowedOrigins;
private $allowedMethods;
private $allowedHeaders;
private $exposedHeaders;
private $allowCredentials;
private $maxAge;
public function __construct(array $config = []) {
$this->allowedOrigins = $config['allowed_origins'] ?? [];
$this->allowedMethods = $config['allowed_methods'] ?? ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'];
$this->allowedHeaders = $config['allowed_headers'] ?? ['Content-Type', 'Authorization', 'X-Requested-With'];
$this->exposedHeaders = $config['exposed_headers'] ?? ['Content-Length', 'X-JSON-Response-Code'];
$this->allowCredentials = $config['allow_credentials'] ?? false;
$this->maxAge = $config['max_age'] ?? 86400;
}
/**
* Get the allowed origin for the current request
*/
public function getOrigin(): ?string {
$origin = $_SERVER['HTTP_ORIGIN'] ?? null;
if (!$origin) {
return null;
}
// Check if origin is in allowed list
if (in_array('*', $this->allowedOrigins)) {
return '*';
}
if (in_array($origin, $this->allowedOrigins)) {
return $origin;
}
return null;
}
/**
* Check if the current request is a preflight OPTIONS request
*/
public function isPreflightRequest(): bool {
return $_SERVER['REQUEST_METHOD'] === 'OPTIONS';
}
/**
* Apply CORS headers to the response
*/
public function applyHeaders(?string $origin = null): void {
if ($origin === null) {
$origin = $this->getOrigin();
}
if (!$origin) {
// If no valid origin, don't set CORS headers
// This ensures blocked origins don't accidentally get access
header('Vary: Origin');
return;
}
header('Access-Control-Allow-Origin: ' . $origin);
header('Access-Control-Allow-Methods: ' . implode(', ', $this->allowedMethods));
header('Access-Control-Allow-Headers: ' . implode(', ', $this->allowedHeaders));
header('Access-Control-Expose-Headers: ' . implode(', ', $this->exposedHeaders));
header('Vary: Origin');
if ($this->allowCredentials) {
header('Access-Control-Allow-Credentials: true');
}
header('Access-Control-Max-Age: ' . $this->maxAge);
}
/**
* Handle preflight OPTIONS request
*/
public function handlePreflight(): void {
$origin = $this->getOrigin();
if ($origin) {
$this->applyHeaders($origin);
http_response_code(204);
exit;
}
http_response_code(403);
exit;
}
/**
* Check if origin is allowed
*/
public function isOriginAllowed(?string $origin = null): bool {
if ($origin === null) {
$origin = $this->getOrigin();
}
if (!$origin) {
return false;
}
if (in_array('*', $this->allowedOrigins)) {
return true;
}
return in_array($origin, $this->allowedOrigins);
}
}