imageDir = __DIR__ . '/../public/images/'; } public function handleRequest(string $method, array $pathSegments): array { // Remove 'images' from path segments array_shift($pathSegments); // Build file path $imagePath = implode('/', $pathSegments); $fullPath = $this->imageDir . $imagePath; // Security check: ensure the path is within the images directory $realPath = realpath($fullPath); $realImageDir = realpath($this->imageDir); if ($realPath === false || strpos($realPath, $realImageDir) !== 0) { http_response_code(403); return ['success' => false, 'error' => 'Access denied']; } // Check if file exists if (!file_exists($realPath)) { http_response_code(404); return ['success' => false, 'error' => 'Image not found']; } // Check if it's actually a file if (!is_file($realPath)) { http_response_code(404); return ['success' => false, 'error' => 'Not a file']; } // Get file info $fileInfo = finfo_open(FILEINFO_MIME_TYPE); $mimeType = finfo_file($fileInfo, $realPath); finfo_close($fileInfo); if ($mimeType === false) { // Fallback to common image types $extension = strtolower(pathinfo($realPath, PATHINFO_EXTENSION)); $mimeTypes = [ 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', 'webp' => 'image/webp', 'svg' => 'image/svg+xml' ]; $mimeType = $mimeTypes[$extension] ?? 'application/octet-stream'; } // Set headers for image serving header('Content-Type: ' . $mimeType); header('Content-Length: ' . filesize($realPath)); header('Cache-Control: public, max-age=31536000'); // Cache for 1 year header('Pragma: public'); // Output the image readfile($realPath); exit; } }