Вы разрабатываете React-приложение, отправляете запрос через Axios к стороннему API и получаете зловещую ошибку в консоли браузера: «Access to XMLHttpRequest at ... has been blocked by CORS policy». Не паникуйте! Эта ошибка — не баг вашего кода, а важный механизм безопасности браузера. В этой статье мы глубоко разберем, что такое CORS, почему он возникает именно в React-приложениях, и главное — как правильно и безопасно его исправить, рассмотрев все возможные способы: от настройки сервера до временных решений для разработки.
Что такое CORS и почему он блокирует ваши запросы?
CORS (Cross-Origin Resource Sharing) — это стандарт безопасности, реализованный во всех современных браузерах. Его основная задача — предотвратить выполнение вредоносными сайтами запросов к другим доменам от имени пользователя без явного разрешения. Когда ваш React-приложение, работающее на localhost:3000, пытается сделать запрос к API на api.example.com, браузер отправляет предварительный «preflight» запрос (типа OPTIONS) для проверки разрешений. Если сервер не отвечает правильными CORS-заголовками, основной запрос блокируется.
Важно: CORS — это ограничение браузера, а не сервера. Сервер может успешно обработать запрос, если отправить его напрямую (например, через Postman или curl), но браузер его не пропустит без правильных заголовков.
Способы исправления CORS ошибки в React + Axios
Решение зависит от того, контролируете ли вы серверную часть (бэкенд) или используете сторонний API.
1. Настройка сервера (идеальное решение)
Если вы владеете бэкендом, необходимо добавить правильные заголовки в ответы сервера. Вот основные заголовки:
Access-Control-Allow-Origin: Указывает, с каких доменов разрешены запросы. Для разработки можно поставить*(все домены), но для продакшена лучше указать конкретный домен вашего фронтенда (например,https://myapp.com).Access-Control-Allow-Methods: Разрешенные HTTP-методы (GET, POST, PUT, DELETE и т.д.).Access-Control-Allow-Headers: Разрешенные заголовки в запросе (например,Content-Type, Authorization).
Пример для Node.js (Express):
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://myfrontend.com'); // Или '*' для разработки
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
2. Использование прокси в режиме разработки (create-react-app)
React-приложения, созданные через create-react-app, поддерживают встроенный прокси. Это временное решение только для этапа разработки. Добавьте в файл package.json строку:
"proxy": "https://api.example.com"
Теперь в вашем Axios-запросе указывайте относительный путь:
axios.get('/api/data') // Запрос пойдет на localhost:3000/api/data, а прокси перенаправит его на api.example.com
Браузер будет думать, что запрос идет на тот же origin, и CORS не сработает.
Примечание: Для более сложных сценариев проксирования создайте файл setupProxy.js в папке src и настройте его с помощью http-proxy-middleware.
3. Настройка кастомных заголовков в Axios
Иногда сервер требует отправки определенных заголовков. Настройте экземпляр Axios глобально или для конкретного запроса:
// Глобальная настройка
axios.defaults.headers.common['Content-Type'] = 'application/json';
// Для конкретного запроса
axios.get('https://api.example.com/data', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Custom-Header': 'value'
}
});
Убедитесь, что эти заголовки разрешены сервером в Access-Control-Allow-Headers.
4. Использование CORS-прокси как временное решение
Для доступа к публичным API, которые не поддерживают CORS, можно использовать публичные CORS-прокси (только для прототипирования и разработки, не для продакшена!).
// Пример с cors-anywhere (демо-версия)
axios.get('https://cors-anywhere.herokuapp.com/https://api.example.com/data')
.then(response => console.log(response.data));
Или разверните свой прокси-сервер на Heroku, Vercel или другом хостинге.
5. Отключение CORS в браузере (крайняя мера для разработки)
Можно запустить браузер с отключенной политикой безопасности. Делайте это только для локальной разработки и тестирования!
- Chrome на Windows/Mac: Закройте все окна Chrome и запустите через терминал/командную строку:
chrome.exe --disable-web-security --user-data-dir="C:/ChromeDevSession" - Используйте расширения типа «Allow CORS: Access-Control-Allow-Origin».
Никогда не просите пользователей отключать CORS в их браузерах — это грубейшая ошибка безопасности.
Структура правильного запроса с Axios
Вот пример правильно настроенного запроса с обработкой ошибок:
import axios from 'axios';
const api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
headers: {
'Content-Type': 'application/json',
},
});
// Перехватчик для добавления токена
tapi.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Использование
api.get('/users')
.then(response => {
console.log('Данные получены:', response.data);
})
.catch(error => {
if (error.response) {
// Сервер ответил с кодом ошибки
console.error('Ошибка сервера:', error.response.status);
} else if (error.request) {
// Запрос был сделан, но ответа нет (возможно, CORS)
console.error('Нет ответа от сервера. Проверьте CORS и сеть.');
} else {
console.error('Ошибка настройки запроса:', error.message);
}
});
FAQ: Часто задаваемые вопросы о CORS
Почему CORS ошибка возникает только в браузере, а Postman работает?
Postman, curl и другие инструменты не являются браузерами и не применяют политику одинакового происхождения (Same-Origin Policy). Они отправляют запросы напрямую, минуя CORS-проверки.
Можно ли обойти CORS на стороне фронтенда без настроек сервера?
Нет, безопасно и правильно — нельзя. Все «обходные» методы (прокси, отключение безопасности) — временные костыли для разработки. Финальное решение всегда требует правильной настройки сервера.
Что такое preflight-запрос и когда он отправляется?
Preflight (предварительный) запрос типа OPTIONS браузер отправляет для «сложных» запросов (не GET/POST с простыми заголовками). Он проверяет, разрешены ли метод и заголовки сервером, до отправки основного запроса.
Как настроить CORS для запросов с авторизацией (куки, токены)?
Сервер должен отправлять заголовок Access-Control-Allow-Credentials: true, а в Access-Control-Allow-Origin должен быть указан конкретный домен (не звездочка). В Axios нужно установить withCredentials: true.
Я получаю CORS ошибку даже при запросе на localhost. Почему?
Если фронтенд и бэкенд работают на разных портах (например, 3000 и 5000), для браузера это разные origins. Используйте прокси (см. выше) или настройте бэкенд на отправку заголовка Access-Control-Allow-Origin: "http://localhost:3000".
Помните: CORS — ваш друг, а не враг. Он защищает пользователей вашего приложения. Правильная его настройка — признак качественной и безопасной веб-разработки.