Как избежать CORS-ошибок при запросах к API

Запросы к API падают, а продукт теряет пользователей — мы настраиваем CORS под ключ и возвращаем стабильный обмен данными между сервисами. Наши инженеры закрывают причину сбоев, а не симптом: выпуск перестаёт зависеть от случайных ошибок интеграции.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Как избежать CORS-ошибок при запросах к API
Простой
~2-3 часа
Часто задаваемые вопросы

Почему запросы к API падают из-за CORS и как это ломает продукт

Ошибка CORS почти никогда не приходит как понятная диагностика — браузер просто блокирует ответ, а в консоли остаётся сухая строка про отсутствующий заголовок. Для продукта это выглядит иначе: форма входа «крутится» без ответа, корзина не подтягивает остатки, интеграция с внешним сервисом молча возвращает пустоту. Пользователь считает, что сервис сломан, хотя бэкенд отработал корректно и вернул данные — их отбросил браузер на этапе проверки политики источника.

Второй типовой сбой — отклонённый предварительный запрос. Браузер перед «сложным» запросом к API отдельно спрашивает у сервера разрешение, и если в ответе нет нужных заголовков, до самого вызова дело не доходит. Отсюда классическая картина: в тестовом окружении всё работает, а на проде запросы к API падают, потому что политика источника настроена под конкретный домен и не учитывает боевой адрес или поддомен. Расхождение окружений по настройке CORS — самая дорогая категория таких сбоев: она не воспроизводится локально и всплывает уже у клиента.

Цена вопроса не в самой ошибке, а в том, как её ищут. Пока команда выясняет, дело в сервере, прокси или фронтенде, релиз стоит, а часть пользователей уходит. Разбираем, как настройка CORS закрывается на уровне конфигурации, чтобы такие отказы не доходили до продакшена.

Что даёт корректная настройка CORS: эффект в цифрах

Корректная настройка CORS убирает целый класс отказов, который иначе всплывает уже в проде: браузер блокирует запрос, фронтенд получает пустой ответ вместо данных, а в логах бэкенда при этом чисто — запрос до сервера просто не доходит. Диагностика такого инцидента занимает часы, потому что симптом виден только в консоли браузера у конкретного пользователя, а не в мониторинге API. Когда политика описана явно — списком разрешённых источников, методов и заголовков, — этот сценарий перестаёт существовать как класс.

Время интеграции сокращается предсказуемо. Пока правила раздаются наугад — «разрешим всё звёздочкой, потом разберёмся», — каждая новая среда, поддомен или отдельный клиент превращается в отдельный раунд отладки: разработчик фронтенда и инженер бэкенда по очереди проверяют, чей заголовок не дошёл. Согласованная политика снимает эти итерации: новый источник добавляется одной правкой конфигурации, а не расследованием.

Стабильность API растёт за счёт того, что разрешения перестают быть всеобщими. Точечные правила не пускают на бэкенд посторонние источники, а предварительные запросы кэшируются браузером — повторные обращения к тем же ручкам идут без лишнего круга согласования. Это заметно на нагруженных экранах, где один рендер тянет десяток запросов.

Выпуск релизов ускоряется, потому что проверка политики становится частью обычного контура: правила лежат в репозитории рядом с кодом, проходят ревью и раскатываются вместе с приложением. Никто не правит их руками на боевом контуре в момент выкладки, а откат возвращает и код, и настройки разом. Именно на стыке этих эффектов — меньше инцидентов, меньше ручной работы, ровнее релизы — и видно, что настройка CORS это не формальность, а часть отказоустойчивости продукта.

Подходы к настройке CORS: сравнение вариантов

Настройка CORS — это всегда выбор точки, в которой приложение получает разрешающие заголовки. Их можно отдавать на самом сервере API, подставлять на промежуточном слое или снять вопрос архитектурно, чтобы браузер вообще не видел кросс-доменный запрос. Ниже — четыре рабочих варианта, между которыми реально выбирают на проектах, с честными ограничениями каждого.

Вариант Когда подходит Ограничения
Разрешающие заголовки на сервере API Свой бэкенд, ограниченный список фронтенд-доменов, нужны cookie и авторизация Список доменов надо поддерживать вручную; при нескольких окружениях легко получить рассинхрон; ошибку в заголовках видно только в браузере
Проксирование через свой домен Сторонний API без доступа к его настройкам, быстрый обход ограничений браузера Прокси становится точкой отказа и требует ресурсов; растёт задержка; нужно отдельно решать авторизацию и лимиты
API-шлюз перед сервисами Несколько сервисов, единые правила доступа, нужна централизованная политика Требует инфраструктуры и сопровождения; для одного сервиса избыточен; правила шлюза надо тестировать отдельно от кода
Ручное управление заголовками в коде Прототип, внутренний инструмент, разовый запрос Дублирование логики в каждом сервисе; при рефакторинге правила теряются; не масштабируется на команду

Разрешающие заголовки на сервере — базовый вариант: он даёт точный контроль над тем, каким доменам и с какими методами разрешены запросы, и корректно работает с сессионными cookie. Проксирование выручает, когда чужой API нельзя трогать: запрос идёт на ваш домен, а сервер уже пересылает его дальше — браузер видит обычный запрос без кросс-доменной проверки.

API-шлюз имеет смысл, когда сервисов больше одного: правила доступа описываются один раз и применяются ко всем, а не расползаются по конфигурациям. Ручная правка заголовков годится только как временное решение — она не переживает рост команды и первый же рефакторинг.

На практике выбор зависит от того, кому принадлежит API и сколько окружений нужно поддерживать. Разберём вашу схему запросов — вернёмся с оценкой, какой вариант закроет задачу без лишнего слоя.

Этапы внедрения: от аудита запросов до передачи регламента

Настройка CORS — это не одна правка в конфиге сервера, а последовательность шагов, где каждый следующий опирается на предыдущий. Если пропустить аудит и сразу выставить заголовки, часть запросов отвалится, а часть останется открытой шире, чем нужно. Поэтому ведём работу по этапам с проверкой на каждом.

  1. Аудит запросов. Собираем все источники, с которых фронтенд обращается к API: домены, поддомены, локальные адреса разработчиков, сторонние виджеты. Фиксируем методы, заголовки и сценарии с учётными данными — именно они чаще всего ломаются при неверной политике.
  2. Проектирование политики. Определяем, какие источники допускаем явно, какие методы и заголовки разрешаем, нужны ли учётные данные и как обрабатываем предварительные запросы. Вместо шаблона «разрешить всем» получаем список правил под реальные сценарии.
  3. Настройка. Переносим правила на сервер и в промежуточный слой: заголовки ответа, обработка предварительных запросов, кэширование разрешений. Отдельно проверяем, что политика не конфликтует с прокси и балансировщиком.
  4. Проверка сценариев. Прогоняем реальные цепочки: вход, загрузка файлов, запросы с учётными данными, обращения со сторонних доменов. Смотрим, что разрешённое проходит, а запрещённое отклоняется с понятной ошибкой.
  5. Документирование. Описываем действующие правила, причины каждого разрешения и порядок добавления нового источника — чтобы следующая правка не превращалась в археологию.
  6. Передача. Отдаём регламент команде, фиксируем ответственных и точки контроля. Политика становится частью процесса, а не разовым патчем.

Такой порядок убирает класс ошибок, когда браузер блокирует запрос, а причина неочевидна. Опишите задачу — вернёмся с оценкой и планом по этапам.

Что заказчик получает на руки: конфигурации и регламенты

Проект закрывается не презентацией, а набором артефактов, по которым другой инженер сможет поднять окружение и повторить настройку без нас. Ниже — что именно передаём по итогам работ над веб-приложением и его взаимодействием с внешними сервисами.

  • Файлы конфигурации — рабочие конфиги для каждого окружения (разработка, тест, продуктив) с явным списком разрешённых источников, методов и заголовков. Отдельно фиксируем, какие значения задаются переменными окружения, а какие зашиты осознанно.
  • Схемы взаимодействия — диаграммы потоков запросов между фронтендом, бэкендом и внешними API: кто инициатор, где проходит предварительный запрос, на каком узле срабатывает политика доступа.
  • Политики доступа — правила, по которым домен попадает в белый список, порядок добавления нового источника и требования к его проверке. Это снимает ситуацию, когда правку вносит первый, кто добрался до конфига.
  • Инструкции по развёртыванию и откату — пошаговый порядок применения изменений с точками возврата: если новая политика ломает интеграцию, откат занимает минуты, а не часы поиска причины.
  • Чек-листы проверки — набор сценариев, которые прогоняются перед выкладкой: запрос с разрешённого домена, с чужого, предварительный запрос, запрос с учётными данными. Каждый пункт — с ожидаемым результатом.
  • Регламент реагирования — что делать, когда в браузере пользователя появляется ошибка доступа: какие данные собрать, где смотреть журналы, кому эскалировать.
  • Журнал изменений политик — кто, когда и зачем расширил список источников. Через полгода это единственный способ понять, почему открыт доступ тому или иному домену.

Комплект рассчитан на то, что команда заказчика ведёт проект сама: конфигурации читаемы, схемы отражают реальное состояние, чек-листы воспроизводимы. Опишите вашу задачу — вернёмся с оценкой и планом, в каком объёме эти артефакты закрывают ваш контур.

Кейс: как мы устранили сбои запросов и ускорили выпуск

Клиент — сервис с личным кабинетом и мобильным приложением — пришёл с симптомом, который команда не могла поймать месяцами: часть запросов к API падала с ошибкой политики безопасности браузера, но только у половины пользователей и только в проде. На стенде всё работало, у разработчиков — тоже. Воспроизводимость нулевая, а жалобы в поддержку росли.

Что нашли

Причина оказалась составной. Обратный прокси отдавал разные заголовки для запросов с Origin и без него, а предварительный запрос OPTIONS на части маршрутов уходил в приложение вместо прокси и возвращал редирект — браузер такой ответ не принимает и блокирует основной запрос. Плюс список разрешённых источников был захардкожен в коде и не покрывал новый поддомен, который добавили под акции. По отдельности каждый фактор безобиден, вместе — плавающие сбои.

Что изменили

Мы вынесли политику в конфигурацию прокси: единый список источников, явная обработка OPTIONS до попадания в приложение, корректный набор Access-Control-Allow-Methods и Access-Control-Allow-Headers под реально используемые методы и заголовки. Для запросов с учётными данными зафиксировали конкретные источники вместо шаблона — браузер не принимает широкий шаблон вместе с передачей сессионных данных. Отдельно закрыли кэширование предварительных ответов, чтобы правки политики применялись без ожидания.

Метрики до и после

Показатель До После
Доля запросов с ошибкой политики 6-9% в часы пик 0
Обращения в поддержку по «не работает вход» 40+ в неделю единичные
Время на добавление нового поддомена 2-3 дня правок и релиз правка конфигурации за минуты
Выпуск изменений в API с опаской, точечно штатный цикл

Отдельный эффект — предсказуемость выпуска. Раньше любая правка доменов или заголовков тянула за собой релиз приложения и ручную проверку, теперь это изменение конфигурации, которое проходит ревью и откатывается одной строкой. Команда перестала бояться трогать интеграции.

Мы работали в связке с их Cloudflare и внутренним прокси, не меняя архитектуру приложения: правки легли на уровень, где им и место. Если у вас похожая картина — сбои «то есть, то нет» и долгий путь любой правки до прода — опишите задачу, вернёмся с оценкой и планом.

Чем отличается настройка CORS на сервере и на шлюзе?

На сервере политику задаёт само приложение: заголовки Access-Control-Allow-Origin, Allow-Methods, Allow-Headers формируются в обработчике или middleware и уходят в каждом ответе. Это даёт максимальную гибкость — правила можно строить на данных запроса: пускать конкретный источник только для определённых маршрутов, подставлять разные наборы методов для чтения и записи, вести журнал отказов рядом с бизнес-логикой. Ограничение одно: политика живёт внутри кода, и при нескольких сервисах её приходится описывать в каждом, рискуя получить расхождения между ними.

Шлюз выносит ту же политику на уровень перед приложениями. Правила описываются декларативно и применяются ко всем маршрутам сразу, единообразно, независимо от того, на чём написан сервис. Предварительный запрос OPTIONS обрабатывается на входе и до приложения не доходит — бэкенд не тратит ресурсы на служебные вызовы. Обратная сторона: шлюз видит только внешний контур запроса и не знает внутренней логики, поэтому тонкие правила вроде «источник A — только для чтения, источник B — только для записи» на нём выражаются грубее.

Ключевое различие — в точке применения политики. На сервере она часть приложения и меняется вместе с релизом; на шлюзе это конфигурация инфраструктуры, которую правят отдельно от кода и раскатывают централизованно. Отсюда и разная цена ошибки: неверный заголовок в коде чинится новым деплоем сервиса, неверное правило на шлюзе — правкой конфигурации без пересборки приложений.

Выбор зависит от контура. Один сервис с несколькими источниками — серверный вариант проще и точнее. Несколько сервисов за общим входом — шлюз убирает дублирование и держит единый стандарт. Часто применяют оба уровня: шлюз закрывает общий периметр и служебные запросы, а приложение донастраивает правила под свои маршруты.

Частые технические сомнения при настройке CORS

Прежде чем менять заголовки ответов, стоит понять: CORS — это не «настройка на сервере», а согласованный контракт между источником запроса и API. Большинство сомнений возникает там, где фронтенд и бэкенд правят свои части независимо и проверяют результат только в браузере — по факту появления ошибки в консоли.

Решение уже развёрнуто, но запросы всё равно падают — что проверять первым?

Смотреть на предварительный запрос: если он уходит и возвращается без нужных заголовков, основной запрос до API вообще не доходит. Дальше — порядок обработки: политика на уровне обратного прокси может перезаписывать то, что выставляет приложение. И третий частый источник — кэш: браузер держит результат предварительного запроса, поэтому правки не видны до сброса. Проверяем цепочку целиком, а не только код приложения.

Как избежать конфликтов между прокси, приложением и внешним сервисом?

Держать один источник истины: список разрешённых источников задаётся в одном месте, остальные слои его только пробрасывают, не дописывая свои значения. Если API отдаёт данные сторонним сайтам, политика описывается отдельно и явно — иначе первый же добавленный домен ломает остальных. Конфликты почти всегда следят за дублированием правил, а не за их содержанием.

Как проверять, что настройка действительно работает?

Автотест на предварительный запрос с реальными источниками и методами — он ловит регресс раньше, чем пользователь. Плюс проверка из браузера с чистым профилем и из командной строки: они показывают разные слои. Отдельно фиксируем поведение при отказах — какой ответ получает клиент, когда источник не разрешён.

Что делать с уже работающими интеграциями при изменении политики?

Вводить изменения поэтапно: сначала расширяем список, наблюдаем за обращениями, только потом убираем лишнее. Логи запросов с отклонёнными источниками дают точную картину, кто ещё ходит к API. Так перестройка проходит без внезапных отказов у смежных команд.

Если по вашей ситуации остались вопросы — опишите текущую схему: где стоит API, кто к нему обращается и как сейчас устроена проверка. Вернёмся с разбором и планом правок.

Обсудим вашу задачу и вернёмся с оценкой и планом

Чтобы вернуться с оценкой и планом, а не с общими словами, нам нужен контекст задачи. Настройка CORS почти никогда не сводится к одному заголовку в ответе сервера — важно, откуда идут запросы, какие методы и заголовки реально используются, есть ли авторизация через cookie, сколько доменов и поддоменов участвует. Чем точнее вы опишете картину, тем меньше итераций уйдёт на согласование.

Опишите задачу в свободной форме — этого достаточно для старта:

  • какие домены и поддомены обращаются к вашему API (фронтенд, мобильное приложение, партнёрские интеграции);
  • какие методы нужны: только чтение или ещё запись, удаление, предварительные запросы;
  • передаются ли учётные данные — cookie, токены в заголовках, сессии;
  • где сейчас возникает ошибка: в браузере, в логах сервера, только у части пользователей;
  • какой стек на фронтенде и бэкенде, кто отвечает за конфигурацию сервера и обратного прокси;
  • есть ли ограничения: требования безопасности, регламенты, запрет на правки в чужом сервисе.

Мы изучим контекст, воспроизведём поведение на вашей схеме запросов и предложим решение — с планом работ, сроками и тем, что нужно с вашей стороны. Если задача решается точечной правкой политики, скажем прямо; если нужна переработка схемы доступа, тоже обозначим честно, без навязывания лишнего объёма.

Обсудим задачу — напишите в удобном канале, приложите примеры запросов и ответов, если они есть. Вернёмся с оценкой и планом.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1393
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060