Когда появляется ошибка Request blocked by CORS policy?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда возникает ошибка "Request blocked by CORS policy"?
Эта ошибка возникает в современных браузерах, когда веб-приложение, работающее в одном источнике (origin), пытается выполнить запрос к ресурсу, размещенному на другом источнике, и сервер этого ресурса не предоставляет правильных заголовков CORS (Cross-Origin Resource Sharing), явно разрешающих такой кросс-доменный запрос. Это механизм безопасности браузеров, предназначенный для предотвращения атак, таких как межсайтовая подделка запроса (CSRF) и утечка конфиденциальных данных.
Ключевые условия возникновения ошибки
Ошибка имеет следующий типичный вид в консоли браузера:
Access to fetch at 'https://api.example.com/data' from origin 'https://myapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Она появляется при одновременном соблюдении трех условий:
- Запрос выполняется из браузера (например, через
fetch(),XMLHttpRequest, или AJAX-вызовы из библиотек). CORS — это политика, применяемая именно браузерами. Запросы с сервера (Node.js, Python) или через инструменты вродеcurlили Postman не сталкиваются с этой блокировкой. - Запрос является кросс-доменным (cross-origin). Происхождение (origin) определяется схемой (
http://,https://), доменом (example.com,api.example.com) и портом (:3000,:8080). Любое несовпадение делает запрос кросс-доменным.
* **Пример:** Приложение на `http://localhost:3000` запрашивает данные с `http://localhost:8080` — **это разные origin (разные порты)**, и будет применена политика CORS.
- Сервер не отправляет корректные заголовки CORS в ответ на данный запрос. Браузер ожидает увидеть в ответе от сервера заголовки, начинающиеся с
Access-Control-Allow-*.
Типы запросов и поведение CORS
Поведение браузера сильно зависит от типа выполняемого запроса:
1. Простые запросы (Simple Requests)
Это GET, HEAD, POST запросы с определенными (безопасными) заголовками (например, Accept, Accept-Language, Content-Language) и типами контента (application/x-www-form-urlencoded, multipart/form-data, text/plain). Для них браузер:
- Немедленно отправляет запрос на сервер.
- Если в ответе нет заголовка
Access-Control-Allow-Origin, содержащего точный источник запроса или символ*, браузер блокирует ответ и выбрасывает ошибку CORS.
2. Непростые запросы (Preflighted Requests)
Запросы, не соответствующие критериям "простых" (например, с пользовательскими заголовками X-API-Key, с типом контента application/json или методы PUT, DELETE), требуют предварительного запроса (preflight).
- Браузер сначала автоматически отправляет OPTIONS-запрос на целевой URL.
- Этот запрос "спрашивает" у сервера: "Разрешены ли такие-то метод и заголовки с моего источника?".
- Сервер должен ответить на этот OPTIONS-запрос заголовками:
HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://myapp.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-API-Key, Content-Type - Если ответ на preflight не содержит нужных разрешений, основной запрос даже не будет отправлен, и в консоли появится ошибка CORS, связанная с preflight.
Практические примеры сценариев
- Разработка на локальном хосте: Фронтенд на
http://localhost:3000пытается получить данные с бэкенд-API наhttp://localhost:5000. - Разделение доменов: Продакшн-фронтенд на
https://myshop.comобращается к платежному шлюзу наhttps://api.payment.com. - Использование внешних API: Приложение на вашем домене делает AJAX-запрос к публичному API, такому как
https://api.weather.com, который может быть сконфигурирован для разрешения запросов только с определенных источников. - Запросы с пользовательскими заголовками: Даже к тому же домену добавление заголовка
Authorization: Bearer ...может превратить запрос в "непростой" и потребовать preflight.
Решения и обходные пути (со стороны клиента и сервера)
Единственное правильное решение — корректно настроить сервер, чтобы он включал необходимые заголовки CORS в ответы. Например, в Node.js с Express:
const express = require('express');
const app = express();
// Middleware для обработки CORS
app.use((req, res, next) => {
// Разрешаем запросы с конкретного origin
res.header('Access-Control-Allow-Origin', 'https://myapp.com');
// Или для всех (небезопасно для продакшна с данными!)
// res.header('Access-Control-Allow-Origin', '*');
// Разрешаемые методы
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
// Разрешаемые заголовки в запросе
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
// Обработка preflight-запроса
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
app.get('/api/data', (req, res) => {
res.json({ message: 'Данные с CORS-заголовками!' });
});
app.listen(5000);
На стороне клиента обходные пути (не всегда применимы и часто являются плохой практикой):
- Прокси-сервер в режиме разработки: Инструменты вроде
webpack-dev-server(proxysetting) илиcreate-react-app(proxyвpackage.json) направляют запросы через ваш dev-сервер, устраняя кросс-доменность. - Отключение CORS в браузере (ТОЛЬКО для разработки): Запуск браузера с флагами, отключающими безопасность (
--disable-web-security), что категорически нельзя использовать для обычного серфинга. - Использование режима
no-corsв fetch: Это позволяет отправить запрос, но делает ответ "непрозрачным" (opaque) — вы не сможете прочитать его тело или статус, что подходит только для очень специфичных сценариев (например, отправки аналитики).
Итог
Ошибка "Request blocked by CORS policy" — это не ошибка вашего кода или сервера в классическом понимании, а стратегический отказ браузера выполнить потенциально небезопасный кросс-доменный запрос. Она служит защитой пользователя. Для её устранения необходимо обеспечить, чтобы сервер, на который направлен запрос, предоставлял клиентскому приложению явные и корректные права доступа через заголовки HTTP-ответа Access-Control-Allow-*.