Представьте себе ситуацию:
вы разрабатываете backend на FastAPI. Ваше приложение идеально работает с фронтендом, который находится на другом домене (например, фронтенд размещен на http://frontend-app.com, а API — на http://backend-api.com). Вы отправляете GET-запрос с фронтенда на backend, но вместо желаемого ответа — браузер сообщает ошибку. Как так? Backend-эндпоинт работает, запросы через Postman проходят… Что же происходит?
Ответ на этот вопрос — CORS.
CORS (Cross-Origin Resource Sharing) — это механизм, который позволяет или запрещает браузерам взаимодействовать с ресурсами, запрашиваемыми с других доменов. Без настроенного CORS браузеры, следуя политике "одного источника" (Same Origin Policy), блокируют такие запросы. Это происходит не из-за ошибок в коде, а из-за встроенной системы безопасности браузеров.
CORS: защита от нежелательных связей
В современном вебе приложения часто размещаются на разных доменах или поддоменах:
- Frontend (
http://frontend-app.com) - Backend (
http://api.backend.com) - CDN для статики (
http://cdn.backend.com)
Без CORS браузер посчитает, что идея передавать данные между "разными доменами" (или источниками) может быть рискованной. А риск реальный: бесконтрольное взаимодействие может привести к атакам, таким как Cross-Site Scripting (XSS) или Cross-Site Request Forgery (CSRF).
Но подождите, ведь взаимодействие API и фронтенда — это нормально и безопасно, если они настраиваются нами. Вот тут CORS и приходит на помощь, чтобы сказать браузеру: "Да, этому фронтенду можно доверять и с ним можно работать".
Как CORS решает проблему
CORS добавляет в заголовки ответа сервера инструкции для браузера:
- Какие методы разрешены? (
GET,POST,DELETE, и т.д.) - Какие домены могут обращаться? (например,
http://frontend-app.com) - Разрешены ли специальные заголовки? (например,
Authorization) - Разрешен ли доступ к cookie?
Без этих заголовков браузер автоматически заблокирует запросы, так как не сможет проверить, "безопасно" ли отдавать данные.
Механизм работы CORS
Все началось с "политики одного источника", которой подчиняются браузеры. Она гласит:
- Запросы считаются безопасными, если они происходят внутри одного источника. Источник (origin) определяется комбинацией:
- Протокола (например, HTTPS)
- Хоста (домен)
- Порта (80, 443 и т.д.)
Пример одного источника:
https://mydomain.com:443→https://mydomain.com:443: окейhttps://mydomain.com→http://mydomain.com: НЕ окей (разные протоколы)https://sub.mydomain.com→https://mydomain.com: НЕ окей (разные поддомены)
Чтобы взаимодействовать между "разными источниками", нужен CORS.
Preflight Request (предварительный запрос)
Иногда браузер перед отправкой основного запроса делает специальный "предварительный запрос" типа OPTIONS.
Этот запрос позволяет браузеру спросить у сервера:
- "Разрешаешь ли ты мне послать запрос с такими-то параметрами и заголовками?"
- "Какие методы и заголовки ты поддерживаешь?"
Если сервер отвечает положительно (добавляет нужные заголовки в ответ), браузер выполняет основной запрос. Иначе — блокирует его.
Пример предварительного запроса:
OPTIONS /data HTTP/1.1
Host: api.backend.com
Origin: http://frontend-app.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization
Ответ сервера:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://frontend-app.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Authorization
Если сервер не ответит подобным образом, браузер скажет: "Нет, это небезопасно", и заблокирует запрос.
Зачем это нужно программисту?
Без понимания CORS ваш backend будет:
- Недоступен для фронтенда.
- Либо — в худшем случае — уязвим для атак, если CORS настроен неаккуратно (например, позволяет запросы отовсюду).
Поэтому каждый разработчик API должен понимать, как включить CORS, и правильно его настраивать:
- Разрешать только те источники, которые действительно должны взаимодействовать.
- Ограничивать методы и заголовки, чтобы минимизировать возможное использование API злоумышленниками.
Где CORS сталкивается с ошибками?
Во время отладки ошибок CORS вы можете встретить следующие неловкие моменты:
- Ошибка "Access-Control-Allow-Origin missing".
Браузер говорит: "Я не вижу заголовкаAccess-Control-Allow-Origin, значит, запрос заблокирован". Это происходит, если сервер не включает CORS в свой ответ или не настроен для работы с вашим источником. - Ошибка "Request header field is not allowed".
Клиентский запрос содержит заголовок (например,Authorization), который не разрешен сервером. Такое часто случается при авторизации. - "CORS policy does not allow...".
Это универсальная ошибка, сообщающая, что сервер не отвечает требованиям браузера.
Если вы наткнулись на CORS-проблему, первое место для проверки — это заголовки ответа сервера.
В реальной жизни
Представьте, что вы пишете API для управления банковскими счетами. Если злоумышленник сможет отправить запросы с другого сайта (без вашего разрешения), это может привести к утечке данных или поддельным транзакциям.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ