143 lines
4.6 KiB
PHP
143 lines
4.6 KiB
PHP
<?php
|
|
/**
|
|
* CORS Configuration for EasyStream API
|
|
*
|
|
* This file handles Cross-Origin Resource Sharing (CORS) headers
|
|
* for all API endpoints in a secure and centralized manner.
|
|
*/
|
|
|
|
/**
|
|
* Set CORS headers based on environment configuration
|
|
*
|
|
* @param array $options Optional CORS configuration
|
|
*/
|
|
function setAPICorsHeaders($options = []) {
|
|
// Get allowed origins from environment or use defaults
|
|
$allowedOrigins = [];
|
|
|
|
// Check if we're in development or production
|
|
$isDevelopment = (defined('_DEVEL') && _DEVEL === true) ||
|
|
(isset($_ENV['APP_ENV']) && $_ENV['APP_ENV'] === 'development');
|
|
|
|
if ($isDevelopment) {
|
|
// Development: Allow localhost and common development ports
|
|
$allowedOrigins = [
|
|
'http://localhost',
|
|
'http://localhost:3000',
|
|
'http://localhost:8080',
|
|
'http://127.0.0.1',
|
|
'http://127.0.0.1:3000',
|
|
'http://127.0.0.1:8080',
|
|
];
|
|
} else {
|
|
// Production: Get from environment variable
|
|
if (isset($_ENV['CORS_ALLOWED_ORIGINS'])) {
|
|
$allowedOrigins = explode(',', $_ENV['CORS_ALLOWED_ORIGINS']);
|
|
} elseif (isset($_SERVER['HTTP_HOST'])) {
|
|
// Default to same origin
|
|
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
|
$allowedOrigins = [$protocol . '://' . $_SERVER['HTTP_HOST']];
|
|
}
|
|
}
|
|
|
|
// Get the origin from the request
|
|
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
|
|
|
|
// Check if origin is allowed
|
|
$isAllowedOrigin = false;
|
|
foreach ($allowedOrigins as $allowedOrigin) {
|
|
$allowedOrigin = trim($allowedOrigin);
|
|
if ($origin === $allowedOrigin || fnmatch($allowedOrigin, $origin)) {
|
|
$isAllowedOrigin = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set CORS headers
|
|
if ($isAllowedOrigin) {
|
|
header('Access-Control-Allow-Origin: ' . $origin);
|
|
header('Access-Control-Allow-Credentials: true');
|
|
} elseif ($isDevelopment) {
|
|
// In development, be more permissive but log it
|
|
header('Access-Control-Allow-Origin: *');
|
|
error_log('CORS: Allowing all origins in development mode');
|
|
}
|
|
|
|
// Set other CORS headers
|
|
$allowedMethods = isset($options['methods'])
|
|
? $options['methods']
|
|
: 'GET, POST, PUT, DELETE, OPTIONS';
|
|
header('Access-Control-Allow-Methods: ' . $allowedMethods);
|
|
|
|
$allowedHeaders = isset($options['headers'])
|
|
? $options['headers']
|
|
: 'Content-Type, Authorization, X-Requested-With, X-CSRF-Token';
|
|
header('Access-Control-Allow-Headers: ' . $allowedHeaders);
|
|
|
|
$maxAge = isset($options['max_age']) ? $options['max_age'] : 86400; // 24 hours
|
|
header('Access-Control-Max-Age: ' . $maxAge);
|
|
|
|
// Expose headers that the client can access
|
|
$exposedHeaders = isset($options['expose_headers'])
|
|
? $options['expose_headers']
|
|
: 'Content-Length, X-JSON';
|
|
header('Access-Control-Expose-Headers: ' . $exposedHeaders);
|
|
}
|
|
|
|
/**
|
|
* Handle preflight OPTIONS request
|
|
*
|
|
* @return void
|
|
*/
|
|
function handleCorsPreflightRequest() {
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
setAPICorsHeaders();
|
|
http_response_code(200);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate origin for sensitive operations
|
|
*
|
|
* @return bool True if origin is valid, false otherwise
|
|
*/
|
|
function validateCorsOrigin() {
|
|
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
|
|
|
|
if (empty($origin)) {
|
|
return true; // Same-origin requests don't have an Origin header
|
|
}
|
|
|
|
// Get server's own origin
|
|
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
|
$serverOrigin = $protocol . '://' . $_SERVER['HTTP_HOST'];
|
|
|
|
// Check if it's the same origin
|
|
if ($origin === $serverOrigin) {
|
|
return true;
|
|
}
|
|
|
|
// Check against allowed origins
|
|
$isDevelopment = (defined('_DEVEL') && _DEVEL === true) ||
|
|
(isset($_ENV['APP_ENV']) && $_ENV['APP_ENV'] === 'development');
|
|
|
|
if ($isDevelopment) {
|
|
// More permissive in development
|
|
return strpos($origin, 'localhost') !== false ||
|
|
strpos($origin, '127.0.0.1') !== false;
|
|
}
|
|
|
|
// Check environment variable
|
|
if (isset($_ENV['CORS_ALLOWED_ORIGINS'])) {
|
|
$allowedOrigins = explode(',', $_ENV['CORS_ALLOWED_ORIGINS']);
|
|
return in_array($origin, array_map('trim', $allowedOrigins));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Automatically set CORS headers and handle preflight when this file is included
|
|
setAPICorsHeaders();
|
|
handleCorsPreflightRequest();
|