Если вы видите эту ошибку — вы не одиноки:
Access to fetch at 'https://api.site.com' from origin 'http://localhost:3000' has been blocked by CORS policy.
Разберем, почему это происходит, и как это починить. Что такое CORS, и для чего он нужен.
CORS (Cross-Origin Resource Sharing) - русского обозначения не имеет. Дословно "межисточниковый" обмен ресурсами.
Цель браузера: защитить пользователя от вредоносных сайтов за счет блокировки запросов к неразрешенным ресурсам.
Как работает:
- Браузер выполняет вызов ресурса.
- Получает заголовки Access-Control.
- Проверяет разрешенные заголовки на соответствие домена и запроса.
- Блокирует или разрешает чтение результата запроса.
Пример: пользователь открывает сайт evil.com. Если bank.com настроил CORS, JavaScript на evil.com не сможет прочитать ответ от bank.com/api/account.
CORS не защищает от кросс-доменных запросов (CSRF-атак). Браузер проверяет заголовки после получения ответа, блокируя передачу ответа в js код.
Заголовки CORS
# Разрешённые домены (один, список или *)
Access-Control-Allow-Origin: https://frontend.com
# Разрешённые HTTP-методы (список или *)
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
# Разрешённые заголовки для отправки(предварительный запрос)
Access-Control-Allow-Headers: Authorization, Content-Type, X-Requested-With
# Разрешённые для чтения заголовки (основной запрос)
Access-Control-Expose-Headers: Authorization, Content-Type, X-Requested-With
# Разрешить передачу кук/токенов
Access-Control-Allow-Credentials: true
# Кэшировать предварительный запрос на 600 сек (10 мин)
Access-Control-Max-Age: 600
Предзапросы (Preflight-запросы)
"Простые запросы" (GET, POST, HEAD без спец. заголовков) отправляются сразу.
"Сложные запросы", например, с методами PUT, DELETE или с нестандартными заголовками, сначала отправляют "предзапрос" (preflight request) методом OPTIONS.
Сервер должен ответить, разрешены ли такие запросы.
Например, перед вызовом GET с заголовком X-API-Key будет выполнен запрос:
http
/data HTTP/1.1
Origin: https://frontend.com
Access-Control-Request-Headers: X-API-Key
Сервер должен ответить:
http
HTTP/1.1 204 OK
Access-Control-Allow-Origin: https://frontend.com
Access-Control-Allow-Headers: X-API-Key
И только потом отправится основной запрос.
Лучшие практики CORS
1.Не используйте * для защищенных данных
Разрешайте только доверенные домены:
Access-Control-Allow-Origin: https://your-frontend.com
2.Для публичных API можно использовать *:
Access-Control-Allow-Origin: *
3.Куки = осторожно!
Если используете куки:
http
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://frontend.com // Нельзя использовать *
4.Тестируйте предзапросы:
Для PUT, DELETE и запросов с Authorization всегда настраивайте обработку OPTIONS.
- Используйте Access-Control-Max-Age чтобы снизить нагрузку
- Настройте веб-сервер (Nginx/Apache) для оптимизации, обработки OPTIONS без запуска приложения
👉 @frontendInterview