Прокси для изображений: решение проблемы CORS через .htaccess и PHP
При разработке расширения для Chrome на JavaScript часто возникает ошибка No 'Access-Control-Allow-Origin' при запросе изображений с внешнего домена. Один из надёжных способов - создать собственный прокси-сервер, который загружает картинки и отдаёт их с нужным заголовком. В этой статье мы разберём, как организовать такую систему с помощью .htaccess и PHP, включая проверку существования папок и файлов.
Архитектура прокси-решения
Основная идея: расширение обращается к вашему домену (https://img.site.ru/images/user/avatar.gif), а сервер проверяет, существует ли файл. Если нет - PHP-скрипт создаёт папки, загружает изображение с исходного домена и возвращает его с заголовком Access-Control-Allow-Origin. Это снижает нагрузку на внешний ресурс и решает проблему CORS.
Настройка .htaccess для маршрутизации запросов
Чтобы все запросы к папке /images/ обрабатывались через PHP, добавьте в корневой .htaccess следующие правила:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^images/(.*)$ index.php?request=$1 [L,QSA]Этот код перенаправляет все несуществующие файлы и папки в index.php с параметром request. Если файл уже существует, он отдаётся напрямую - без нагрузки на PHP.
PHP-скрипт для обработки запросов
В index.php реализуем логику проверки и загрузки:
<?php
header('Access-Control-Allow-Origin: *');
$request = $_GET['request'] ?? '';
if (!$request || !is_string($request) || strpos($request, '..') !== false) {
header('Location: https://img.site.ru');
exit;
}
$fullPath = __DIR__ . '/' . $request;
if (file_exists($fullPath)) {
$mime = mime_content_type($fullPath);
header('Content-Type: ' . $mime);
readfile($fullPath);
exit;
}
$dir = dirname($fullPath);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
$remoteUrl = 'https://source-domain.com/' . $request;
$imageData = file_get_contents($remoteUrl);
if ($imageData !== false) {
file_put_contents($fullPath, $imageData);
header('Content-Type: image/png');
echo $imageData;
} else {
http_response_code(500);
echo 'Ошибка загрузки изображения';
}
?>Скрипт проверяет наличие файла, создаёт папки при необходимости, загружает изображение с удалённого сервера и сохраняет его локально. Также добавлена базовая защита от path traversal.
Обеспечение безопасности поддомена
Чтобы предотвратить злоупотребления, следуйте этим рекомендациям:
- Ограничьте типы файлов: разрешите только изображения (png, jpg, gif, webp) через проверку расширения.
- Защита от path traversal: запретите использование
..в пути. - Ограничьте размер файла: используйте
filesize()или лимиты на стороне PHP. - Кэширование: добавьте заголовки
Cache-Controlдля уменьшения нагрузки.
Альтернативный подход: прямой запрос через ?request=
Можно отказаться от .htaccess и просто делать запросы к https://img.site.ru/?request=images/avatar.png. Этот вариант проще, но менее красив с точки зрения URL. Выбор зависит от ваших требований к эстетике ссылок.
Обработка ошибок и редиректы
При неверном запросе (например, отсутствует параметр request или он содержит недопустимые символы) лучше всего перенаправлять пользователя на главную страницу домена или возвращать 404. В примере выше используется редирект на https://img.site.ru.