Вы разрабатываете крутое React-приложение, подключаетесь к API через axios, и вдруг — красная ошибка в консоли: "CORS policy blocked". Знакомо? Эта ошибка безопасности браузера останавливает многих разработчиков, но на самом деле её решение — это не магия, а понимание механизмов безопасности современного веба. В этой статье мы разберём CORS от А до Я и покажем все рабочие способы исправить проблему в вашем проекте.
Что такое CORS и почему браузер блокирует запросы?
CORS (Cross-Origin Resource Sharing) — это механизм безопасности браузера, который ограничивает кросс-доменные HTTP-запросы. Когда ваш React-приложение на localhost:3000 пытается получить данные с api.example.com, браузер отправляет предварительный запрос (preflight) с методом OPTIONS, чтобы проверить, разрешён ли доступ.
CORS работает только в браузерах! Если вы делаете запрос через Postman, cURL или Node.js-сервер — ошибки не будет. Это исключительно браузерная защита.
Типичная ошибка в React + Axios
Вот как выглядит стандартный код, вызывающий проблему:
import axios from 'axios';
const fetchData = async () => {
try {
const response = await axios.get('https://api.other-domain.com/data');
console.log(response.data);
} catch (error) {
console.error('CORS Error:', error);
}
};
И соответствующая ошибка в консоли: "Access to XMLHttpRequest at 'https://api.other-domain.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy".
5 рабочих способов исправить CORS ошибку
1. Настройка сервера (правильный способ)
Идеальное решение — добавить правильные CORS-заголовки на стороне сервера:
- Access-Control-Allow-Origin: Укажите ваш домен или '*' для всех доменов
- Access-Control-Allow-Methods: Разрешите методы (GET, POST, PUT и т.д.)
- Access-Control-Allow-Headers: Разрешите необходимые заголовки
Пример для Node.js + Express:
const cors = require('cors');
app.use(cors({
origin: 'http://localhost:3000',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
2. Прокси-сервер в development-режиме
Create React App позволяет настроить прокси в package.json:
{
"proxy": "https://api.other-domain.com"
}
Или создайте файл setupProxy.js:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'https://api.other-domain.com',
changeOrigin: true,
pathRewrite: {'^/api': ''},
})
);
};
3. Использование CORS-прокси сервисов
Для публичных API, которые вы не контролируете:
- cors-anywhere.herokuapp.com (для разработки)
- allorigins.win
- Собственный прокси на Vercel/Netlify
axios.get('https://cors-anywhere.herokuapp.com/https://api.target.com/data');
Публичные CORS-прокси не подходят для продакшена! Они могут быть медленными, ненадёжными и небезопасными для приватных данных.
4. Отключение CORS в браузере (только для разработки!)
Временное решение для локальной разработки:
- Chrome: Запуск с флагом --disable-web-security
- Использование расширения CORS Unblock
- Приложение CORS Everywhere для Firefox
5. JSONP как альтернатива для GET-запросов
Старый, но рабочий метод для публичных API:
const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleData';
document.body.appendChild(script);
window.handleData = (data) => {
console.log('Received:', data);
};
Продвинутые сценарии с Axios
Настройка экземпляра Axios с CORS
const api = axios.create({
baseURL: 'https://api.example.com',
withCredentials: true, // Для отправки cookies
headers: {
'Content-Type': 'application/json',
}
});
// Добавление интерцепторов для CORS
api.interceptors.request.use(config => {
config.headers['X-Requested-With'] = 'XMLHttpRequest';
return config;
});
Обработка preflight-запросов
Для сложных запросов (с кастомными заголовками или Content-Type) браузер отправляет OPTIONS-запрос. Убедитесь, что ваш сервер правильно на него отвечает:
// Серверная обработка OPTIONS
app.options('/data', (req, res) => {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.sendStatus(200);
});
Лучшие практики и безопасность
- Никогда не используйте Access-Control-Allow-Origin: * в продакшене с приватными данными
- Всегда валидируйте Origin на сервере
- Используйте environment variables для доменов
- Для production используйте белый список разрешённых доменов
- Регулярно обновляйте CORS-политики
FAQ: Частые вопросы о CORS
Почему CORS ошибка возникает только в браузере?
CORS — это механизм безопасности браузеров. Серверные приложения (Node.js, Python) и инструменты типа Postman не имеют таких ограничений.
Как отличить CORS ошибку от других?
CORS ошибка всегда содержит фразы "CORS policy", "Access-Control-Allow-Origin" или "cross-origin" в сообщении. Код статуса может быть 200, но браузер блокирует ответ.
Работает ли CORS с куками?
Да, но нужно установить withCredentials: true в Axios и Access-Control-Allow-Credentials: true на сервере. При этом Access-Control-Allow-Origin не может быть '*'.
Что делать если я не контролирую сервер API?
Используйте backend-прокси на вашем сервере или сервисы типа Cloudflare Workers для создания CORS-прослойки.
Как настроить CORS для нескольких доменов?
На сервере проверяйте Origin заголовок и динамически устанавливайте Access-Control-Allow-Origin для разрешённых доменов.
Помните: CORS — это функция безопасности, а не баг. Правильная настройка CORS защищает пользователей от межсайтовых атак и утечек данных.
Теперь вы вооружены всеми необходимыми знаниями для борьбы с CORS ошибками в React-приложениях. Начните с правильной настройки сервера, используйте прокси для разработки и никогда не отключайте CORS в production. Удачного кодинга!