Что такое CORS? Почему возникает ошибка и как её правильно устранять?
Короткий ответ
- Same-Origin Policy запрещает читать ответы чужого origin
- Origin — это схема, домен и порт вместе
- CORS — механизм, которым сервер ослабляет этот запрет
- Сервер разрешает доступ заголовком Access-Control-Allow-Origin
- «Непростые» запросы предваряются preflight-запросом OPTIONS
- Для кук нужны credentials и точный origin, не звёздочка
- Чинится на сервере или через прокси, не хаками в браузере
CORS — это серверное разрешение на межсайтовые запросы поверх Same-Origin Policy браузера; ошибка означает, что сервер не прислал нужные заголовки, и чинится на стороне сервера или через прокси.
Как сказать вслух
пример ответаВ браузере действует политика одного источника: скрипт со страницы не может прочитать ответ API с другого домена, это защита пользователя. CORS — механизм, которым сервер явно говорит браузеру: вот этим источникам отвечать можно. Если в ответе нет нужного заголовка, браузер сам блокирует чтение — отсюда знаменитая ошибка в консоли. Для запросов с нестандартными заголовками или методами браузер сначала шлёт проверочный запрос OPTIONS. Чинится это настройкой сервера или прокси, а не трюками на фронтенде.
Подробный ответ
Основной ответ
Origin — тройка «схема + хост + порт»; отличие любой части делает запрос кросс-доменным. Браузер отправляет такой запрос с заголовком Origin, но не даёт JS прочитать ответ, пока сервер не вернёт Access-Control-Allow-Origin с этим источником (или *). Запросы делятся на «простые» (GET/POST/HEAD с безопасными заголовками) и остальные: перед PUT, DELETE или запросом с Authorization либо Content-Type: application/json браузер шлёт preflight — OPTIONS с Access-Control-Request-Method и Access-Control-Request-Headers, и сервер должен подтвердить их в ответных заголовках; результат кэшируется через Access-Control-Max-Age. Для запросов с куками нужно credentials: 'include' на клиенте и Access-Control-Allow-Credentials: true плюс конкретный origin на сервере — со звёздочкой это не работает. Важно: CORS защищает пользователя браузера, а не API — запрос с сервера или из curl он не ограничивает.
Ключевые моменты
- Это политика браузера. Сервер запрос чаще всего получает и обрабатывает; блокирует чтение ответа именно браузер.
- Preflight. «Непростые» запросы требуют предварительного OPTIONS; лишние кастомные заголовки удваивают число запросов.
- Куки и credentials. Связка credentials: include, Allow-Credentials: true и явный origin обязательна для сессий на куках.
- Правильные решения. Настроить заголовки на API, поднять прокси на своём бэкенде или dev-сервере; wildcard на проде с credentials — дыра.
Практический контекст
С CORS сталкивается каждый фронтендер при локальной разработке против чужого API. Интервьюер проверяет, понимает ли кандидат, что это не «баг», а защитный механизм, и где его чинить. Хороший ответ включает дев-прокси (vite server.proxy, nginx), объяснение, почему «запрос в Postman работает, а в браузере нет», и понимание, что отключать проверку в браузере или ставить «anywhere»-прокси в прод нельзя.
Частые ошибки
- Пытаются «починить CORS с фронтенда», добавляя заголовки в запрос — разрешение даёт только сервер
- Не знают про preflight и удивляются запросам OPTIONS в сети
- Ставят Access-Control-Allow-Origin: * вместе с куками и не понимают, почему не работает