Понимание CORS: почему браузер блокирует запросы
Что такое CORS и зачем он нужен
CORS (Cross-Origin Resource Sharing) — это механизм безопасности, реализованный в современных браузерах, который ограничивает выполнение HTTP-запросов к ресурсам на другом домене, если они не разрешены сервером. Проще говоря, если ваш фронтенд размещён на `example.com`, а вы пытаетесь сделать запрос к API на `api.example.org`, браузер по умолчанию заблокирует его, считая кросс-доменным. CORS — не ошибка, а защита от возможных XSS-атак, когда вредоносный скрипт получает доступ к данным другого сайта.
Без корректной настройки CORS сервер вернёт заголовок, запрещающий доступ, или вовсе не отправит нужные заголовки, и тогда браузер выдаст типичную ошибку: `Access to fetch at 'https://api.example.org/data' from origin 'https://example.com' has been blocked by CORS policy`.
Как работает механизм CORS на техническом уровне
Когда браузер отправляет кросс-доменные запросы, он делает это в два этапа. В случае «простых» запросов (например, `GET` без нестандартных заголовков) отправляется основной запрос сразу. Однако если в запросе есть нестандартные заголовки (`Authorization`, `Content-Type: application/json` и др.), или используется метод `PUT`, `DELETE`, то сначала отправляется так называемый preflight-запрос методом `OPTIONS`.
Этот предварительный запрос проверяет, позволяет ли сервер выполнение основного запроса. Если сервер не отвечает с нужными HTTP-заголовками, такими как `Access-Control-Allow-Origin`, `Access-Control-Allow-Methods`, браузер блокирует запрос.
Пример preflight-запроса:
```
OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
```
И ожидаемый ответ от сервера:
```
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type
```
Типичные причины CORS-ошибок и как их исправить
Наиболее распространённые ошибки и их диагностика
Разработчики часто сталкиваются с ошибками CORS при работе с REST API, особенно на стадии локальной разработки. Одним из частых случаев является попытка выполнить запрос с фронтенда к API, размещённому на другом домене или порту. Браузер в этом случае выдает ошибку вида:
> Access to XMLHttpRequest at 'https://api.example.org/data' from origin 'http://localhost:3000' has been blocked by CORS policy.
Чтобы понять, как исправить ошибки CORS, необходимо:
1. Проверить, отправляется ли preflight-запрос.
2. Проанализировать ответ сервера: присутствуют ли нужные заголовки.
3. Убедиться, что сервер действительно поддерживает указанный origin.
Подходы к решению: серверная настройка

Наиболее корректный способ решения проблемы CORS — настройка соответствующих заголовков на сервере. Ниже приведены способы настройки для популярных технологий:
1. Node.js (Express):
```javascript
const cors = require('cors');
app.use(cors({ origin: 'http://localhost:3000' }));
```
2. Python (Flask):
```python
from flask_cors import CORS
CORS(app, origins="http://localhost:3000")
```
3. Nginx (проксирование):
```
location /api/ {
add_header 'Access-Control-Allow-Origin' 'http://localhost:3000';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
}
```
Это предпочтительный способ, особенно в продакшене. Он безопасен, контролируем и масштабируем.
Альтернативные подходы: проксирование и заглушки
Иногда настройка CORS невозможна, особенно если вы работаете с внешним API, не поддерживающим нужные заголовки. В этом случае есть обходные пути:
1. Настройка прокси-сервера. Например, в React можно настроить `proxy` в `package.json`:
```json
"proxy": "https://api.example.org"
```
Это позволяет отправлять запросы через фронтенд-сервер, который будет проксировать их на внешний API, скрывая от браузера факт кросс-домена.
2. Использование серверной прослойки. Вы можете создать промежуточный сервер (middleware), который будет отправлять запросы к API от своего имени, а фронтенд будет обращаться только к вашему серверу.
3. CORS-заглушки и расширения. На этапе разработки можно использовать браузерные расширения (например, Allow CORS: Access-Control-Allow-Origin), но это решение категорически не подходит для продакшена.
Сравнение подходов: плюсы и минусы
1. Настройка CORS на сервере
- ✅ Безопасно, прозрачно
- ✅ Поддерживается всеми браузерами
- ❌ Требует доступа к серверу
- ❌ Нужно следить за безопасностью (не использовать `*` в `Access-Control-Allow-Origin`)
2. Проксирование через фронтенд
- ✅ Быстрый старт
- ✅ Не требует изменения API
- ❌ Может ломаться при сложных конфигурациях
- ❌ Не решает проблему во всех случаях (preflight всё равно может сработать)
3. Серверный middleware
- ✅ Гибко и контролируемо
- ✅ Полный контроль над запросами
- ❌ Увеличивает сложность архитектуры
- ❌ Может повлиять на производительность
Рекомендации для начинающих разработчиков

Если вы только начинаете работать с веб-разработкой и не понимаете, почему браузер блокирует ваши запросы — изучите, что такое CORS для начинающих. Начните с анализа заголовков запроса и ответа в DevTools (вкладка Network). Обратите внимание на наличие `Access-Control-Allow-Origin` и значение заголовка `Origin`.
Вот пошаговая инструкция, как исправить ошибки CORS:
1. Определите, к какому домену направлен запрос и отличается ли он от origin страницы.
2. Убедитесь, что сервер возвращает нужные заголовки CORS.
3. При необходимости — настройте прокси или middleware.
4. Не используйте `Access-Control-Allow-Origin: *` вместе с `credentials: true` — это вызовет ошибку.
5. Тестируйте запросы через curl или Postman, чтобы исключить ошибки, не связанные с CORS.
Заключение
Ошибки CORS — это не баг, а защита браузера. Их появление означает, что ваш клиент пытается получить доступ к ресурсу, который не разрешает такие запросы. Настройка CORS — важный этап в разработке API и фронтенда, особенно при работе в распределённых системах. Понимание механизма и правильный выбор стратегии — будь то настройка заголовков, проксирование или middleware — помогут вам избежать проблем и обеспечить безопасное взаимодействие между клиентом и сервером.



