Что такое CORS и почему появляется ошибка
CORS (Cross‑Origin Resource Sharing) — механизм, реализованный в браузерах для ограничения запросов к ресурсам, находящимся на другом домене, порте или протоколе. Когда клиентский скрипт пытается обратиться к API, размещённому, например, на https://api.example.com, а страница загружается с http://localhost:3000, браузер рассматривает такой запрос как кросс‑origin и проверяет наличие специальных заголовков в ответе сервера.
Ключевой заголовок — Access-Control-Allow-Origin. Если сервер его не отправил или значение не совпадает с текущим Origin, браузер блокирует запрос и выводит в консоль сообщение вида:
Access to fetch at 'https://api.example.com' from origin 'http://localhost:3000' has been blocked by CORS policy
Важно помнить, что CORS контролируется клиентским браузером, а не сервером. Поэтому исправить проблему можно только на стороне сервера, добавив необходимые заголовки в HTTP‑ответы.
Настройка CORS в Node.js (Express)
Для приложений на базе Express существует готовый middleware cors, который автоматически формирует нужные заголовки. Ниже описан минимальный набор шагов.
- Установить пакет
npm install cors
- Подключить и использовать middleware
const express = require('express');
const cors = require('cors');
const app = express();
// Разрешить запросы со всех источников
app.use(cors());
// Если нужен более строгий контроль, можно передать объект настроек:
// app.use(cors({ origin: 'http://localhost:3000', methods: ['GET','POST'] }));
app.get('/api/data', (req, res) => {
res.json({ message: 'CORS настроен корректно' });
});
app.listen(5000, () => {
console.log('Server running on port 5000');
});
- Перезапустить сервер и проверить запрос через браузер или
curl. При корректной конфигурации в ответе появятся заголовкиAccess-Control-Allow-Origin,Access-Control-Allow-Methodsи др., а браузер выполнит запрос без блокировки.
Обработка предварительных запросов (preflight)
Для методов, отличных от GET/POST, или при наличии нестандартных заголовков браузер отправляет OPTIONS‑запрос. Middleware cors автоматически отвечает на такие запросы, но если вы пишете собственную обработку, необходимо вернуть минимум:
app.options('*', cors()); // разрешить preflight для всех роутов
Настройка CORS в PHP
В PHP добавление заголовков происходит через функцию header(). Их следует разместить в начале скрипта, до любого вывода.
<?php
// Разрешить запросы с любого домена
header('Access-Control-Allow-Origin: *');
// Указать поддерживаемые методы
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
// Перечислить разрешённые заголовки запроса
header('Access-Control-Allow-Headers: Content-Type, Authorization');
// Обработка предварительных запросов
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
// Останавливаем скрипт, отправляя только заголовки
exit(0);
}
// Основная логика API
echo json_encode(['message' => 'CORS включён']);
?>
Для более строгой политики вместо * указывайте конкретный Origin, например http://localhost:3000. Это повышает безопасность и упрощает аудит доступа.
Лучшие практики для продакшн‑окружения
-
Не использовать «*» в продакшн – открытый доступ к API делает сервис уязвимым к CSRF‑атакам и злоупотреблениям. Указывайте конкретные домены, которые действительно нуждаются в доступе.
-
Ограничьте методы и заголовки – разрешайте только те HTTP‑методы и заголовки, которые действительно требуются вашему клиенту. Это уменьшает поверхность атаки.
-
Включайте
Access-Control-Max-Age– позволяет браузеру кэшировать результаты preflight‑запросов, снижая количество лишних запросов:Access-Control-Max-Age: 86400 -
Обрабатывайте ошибки CORS явно – если запрос отклонён, возвращайте понятный статус (например, 403) и сообщение в теле ответа. Это упрощает отладку на клиенте.
-
Тестируйте в разных браузерах – хотя стандарт CORS одинаков, реализация может слегка отличаться (особенно в старых версиях IE). Автоматические тесты, использующие
fetchилиaxios, помогут обнаружить проблемы до релиза. -
Разделяйте конфигурацию от кода – храните список разрешённых Origin в переменных окружения или конфигурационных файлах. При смене домена достаточно обновить конфигурацию без правки кода.
Следуя этим рекомендациям, вы сможете быстро устранить типичную ошибку «Blocked by CORS Policy», обеспечить безопасный обмен данными между фронтендом и бэкендом и избежать повторных проблем при масштабировании проекта.