CORS в React и Axios: Полное руководство по исправлению ошибок настройки доступа

CORS в React и Axios: Полное руководство по исправлению ошибок настройки доступа

Вы разрабатываете 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 — ваш друг, а не враг. Он защищает пользователей вашего приложения. Правильная его настройка — признак качественной и безопасной веб-разработки.