Мы часто сталкиваемся с ситуацией, когда фронтенд-приложение на app.example.com обращается к API на api.example.com (или к REST-методам Битрикс24), а браузер блокирует запрос из-за CORS. Классическая боль: разработчик часами ищет ошибку, хотя проблема решается добавлением трёх заголовков. Настройка CORS — это не про защиту сервера (серверные запросы CORS не касаются), а про то, чтобы браузер разрешил вашему JavaScript работать с кросс-доменными запросами. За 10+ лет работы с Битрикс мы решили CORS-проблемы для 200+ проектов, экономя клиентам в среднем $200–400 на отладке.
Как работают CORS-запросы?
CORS (Cross-Origin Resource Sharing) — механизм безопасности браузера, блокирующий запросы к домену, отличному от домена страницы. Simple requests (GET, POST с Content-Type: application/x-www-form-urlencoded) браузер отправляет напрямую, но проверяет ответ: если нет заголовка Access-Control-Allow-Origin с нужным значением — JavaScript не получит ответ (запрос ушёл, ответ получен сервером, но браузер скрыл его от JS). Preflight requests — для нестандартных методов (PUT, DELETE, PATCH) и заголовков (Authorization, Content-Type: application/json). Браузер сначала отправляет OPTIONS-запрос («можно мне это?»), сервер отвечает — и только потом браузер отправляет основной запрос.
Когда нужен preflight-запрос?
Любой запрос с отличным от application/x-www-form-urlencoded Content-Type, например application/json, или с кастомным заголовком (например, X-API-Key) вызовет preflight. Также preflight возникает при использовании методов, отличных от GET/POST. Эту особенность важно учитывать при проектировании REST API — если ваш клиент отправляет JSON, готовьтесь обрабатывать OPTIONS.
Как настроить CORS на Nginx?
Для API на коробочном Битрикс — CORS лучше настраивать в Nginx, не в PHP. Nginx обработает OPTIONS-preflight без запуска PHP, что даёт выигрыш в производительности — до 15 мс на запрос.
location /api/ { # Список разрешённых источников set $cors_origin ""; if ($http_origin ~* "^https://(app\.example\.com|admin\.example\.com)$") { set $cors_origin $http_origin; } # Preflight OPTIONS if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, PATCH, OPTIONS" always; add_header Access-Control-Allow-Headers "Authorization, Content-Type, X-API-Key" always; add_header Access-Control-Max-Age 3600 always; add_header Content-Length 0; return 204; } add_header Access-Control-Allow-Origin $cors_origin always; add_header Access-Control-Allow-Credentials true always; proxy_pass http://php_backend; } Access-Control-Allow-Credentials: true — нужен, если запросы идут с cookie (сессии Битрикс). При этом Access-Control-Allow-Origin не может быть * — только конкретный домен.
Настройка через PHP (init.php или middleware)
Если CORS нужно настраивать динамически (разные правила для разных эндпоинтов, список источников из БД):
// /local/php_interface/init.php или middleware API $allowedOrigins = ['https://app.example.com', 'https://admin.example.com']; $origin = $_SERVER['HTTP_ORIGIN'] ?? ''; if (in_array($origin, $allowedOrigins)) { header('Access-Control-Allow-Origin: ' . $origin); header('Access-Control-Allow-Credentials: true'); header('Vary: Origin'); // Важно для корректного кеширования CDN } if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS'); header('Access-Control-Allow-Headers: Authorization, Content-Type, X-API-Key'); header('Access-Control-Max-Age: 3600'); http_response_code(204); exit; } Заголовок Vary: Origin обязателен при динамическом CORS — MDN Web Docs рекомендует его для корректного кеширования CDN.
CORS для Битрикс24 REST API
Облачный Битрикс24 настроить нельзя — заголовки CORS управляются на стороне Битрикс. Для запросов из браузера к portal.bitrix24.ru/rest/ используйте встроенный JS-SDK (BX24.callMethod), который работает внутри iframe приложения и не подвержен CORS-ограничениям. Прямые REST-запросы из браузера к чужому домену Битрикс24 потребуют проксирования через ваш сервер. Подробнее в официальной документации.
Почему нельзя использовать * с credentials?
Access-Control-Allow-Origin: * разрешает всем. Но при Access-Control-Allow-Credentials: true это недопустимо — браузер заблокирует такой ответ. Только конкретные домены.
Валидируйте список источников. Проверку if ($origin === 'https://app.example.com') обходит атакующий с заголовком Origin: https://app.example.com. Нет — это не обход: CORS защищает от браузерных атак, а не от curl. Серверные запросы CORS игнорируют.
Preflight кеш (Max-Age). Значение 3600 означает: браузер не отправляет повторный OPTIONS-запрос в течение часа. Слишком большое значение замедляет обнаружение изменений политики CORS.
Типичные сценарии, когда нужно настраивать CORS
| Сценарий | Рекомендация |
|---|---|
| Фронтенд на том же домене | CORS не нужен |
Фронтенд на поддомене (app.example.com → api.example.com) |
CORS с конкретным origin |
| Публичный API для партнёров | CORS * (без credentials) |
| Мобильное приложение (не браузер) | CORS не нужен, запросы серверные |
| Несколько фронтенд-клиентов | Динамический список + Vary: Origin |
Как решить типичные ошибки CORS?
| Ошибка | Причина | Решение |
|---|---|---|
No 'Access-Control-Allow-Origin' |
Заголовок не отправлен или несовпадение origin | Добавить заголовок с правильным origin |
Response to preflight request doesn't pass access control check |
OPTIONS-запрос не получил корректный ответ | Обработать OPTIONS, вернуть 200 или 204 с заголовками |
Request header field X-API-Key is not allowed by Access-Control-Allow-Headers |
Кастомный заголовок не разрешён | Добавить заголовок в Access-Control-Allow-Headers |
Method PUT is not allowed by Access-Control-Allow-Methods |
Метод не разрешён | Расширить список методов в preflight |
Что входит в работу
- Аудит текущей конфигурации CORS и выявление проблем — 95% проблем выявляются за 30 минут.
- Настройка CORS на Nginx или Apache (в зависимости от окружения).
- Реализация динамического CORS через PHP (если требуется).
- Разработка прокси-сервера для Битрикс24 REST (если необходимо).
- Тестирование всех сценариев (simple, preflight, с credentials) — в среднем 8 кейсов.
- Документация и рекомендации по дальнейшей поддержке.
Как настроить CORS: пошаговая инструкция
- Определите список разрешённых источников (origin).
- Выберите способ настройки: Nginx (static) или PHP (dynamic).
- Добавьте обработку OPTIONS-запросов с нужными заголовками.
- Установите
Access-Control-Allow-Credentials: trueдля запросов с сессиями. - Протестируйте через curl или браузерные инструменты разработчика.
Настройка CORS — это 30 минут работы при правильном понимании механизма. Большинство проблем с CORS решаются правильным расположением заголовков (до вывода тела ответа) и корректной обработкой OPTIONS-запросов. Если вы хотите избежать часов отладки — доверьте эту задачу профессионалам. Свяжитесь с нами, чтобы получить консультацию по вашему проекту. Мы гарантируем, что после настройки ваш API будет корректно работать с любыми браузерными клиентами.







