Что такое политика CORS и как она работает
Что проверяют
Понимаете ли вы, что ограничение накладывает браузер, а не сервер, и умеете ли читать ошибку в консоли. Фронтендер встречается с этим каждую неделю, и собеседующий ждёт рабочую модель: кто кого проверяет и в какой момент, а не расшифровку аббревиатуры.
Как отвечать
Базовое правило браузера это правило одного источника: скрипт со страницы одного источника (схема, домен, порт) не может прочитать ответ от другого источника. CORS ничего не запрещает, наоборот: это набор ответных заголовков, которыми сервер разрешает браузеру отдать ответ коду страницы.
Механика простая. Браузер добавляет к кросс-доменному запросу заголовок Origin, сервер отвечает Access-Control-Allow-Origin. Не совпало, и ответ до кода не доедет, хотя запрос дошёл до сервера и был обработан.
Простые запросы уходят сразу. Если метод не GET, HEAD и не POST, либо стоит нестандартный заголовок вроде Authorization или тип содержимого application/json, браузер сначала шлёт предварительный OPTIONS и ждёт Access-Control-Allow-Methods и Access-Control-Allow-Headers, а Access-Control-Max-Age кэширует это разрешение.
Для запросов с куками нужны credentials: "include" на клиенте и Access-Control-Allow-Credentials: true вместе с конкретным источником на сервере: ответ со звёздочкой браузер в этом режиме отбракует.
Где спотыкаются
Говорят, что политика защищает сервер или спасает от подделки межсайтовых запросов. Ни того ни другого: любой не браузерный клиент заголовки просто игнорирует, а от подделки запросов защищают токен и атрибут SameSite у куки.
Лечат ошибку на клиенте: дописывают Access-Control-Allow-Origin в запрос или ставят mode: "no-cors" и удивляются пустому ответу. Разрешение выдаёт только сервер, а на своей стороне остаётся прокси на собственном источнике.
Не проверяют предварительный запрос отдельно. OPTIONS ушёл на роут, где обработчик написан только для POST, вернулся 404 или 401, и в консоли видно лишь общую фразу про запрещённый доступ.