🛡 Почему запрос работает в Postman, но не в браузере?
Ситуация до боли знакомая: дёргаешь API в Postman — всё ок, статус 200, тело ответа на месте. Открываешь фронтенд в браузере — в консоли красная ошибка CORS, запрос заблокирован. Давай разложим по полочкам, почему так происходит, и что с этим делать тестировщику.
🌐 Что такое CORS и при чём тут браузер? CORS (Cross-Origin Resource Sharing) — механизм безопасности, встроенный в браузеры. Он основан на Same-Origin Policy: JavaScript с одного источника (домен, порт, протокол) не может просто так читать ответы с другого источника. Чтобы сервер разрешил кросс-доменный доступ, он должен вернуть специальные HTTP-заголовки:
· Access-Control-Allow-Origin (кто может читать ответ) · Access-Control-Allow-Methods, Access-Control-Allow-Headers и т.д.
Если этих заголовков нет — браузер заблокирует ответ для JavaScript-кода, даже если сервер фактически ответил 200 OK.
💻 Почему Postman работает без проблем? Postman — не браузер, а инструмент для разработчиков. Он не применяет Same-Origin Policy и не заботится о безопасности кросс-доменных запросов. Ему всё равно, какие CORS-заголовки вернул сервер: он просто показывает пришедший HTTP-ответ как есть. К тому же Postman обычно не отправляет preflight-запросы (OPTIONS), которые браузер посылает перед «сложными» запросами (например, с кастомными заголовками, методами PUT/DELETE или Content-Type: application/json). Postman просто выполняет основной запрос, поэтому ты видишь успешный ответ, а браузер на preflight уже ловит пустой ответ без Allow-заголовков и блокирует вызов.
🧠 Что происходит в браузере на самом деле? Когда фронтенд делает кросс-доменный запрос, браузер проверяет:
1. Простой ли это запрос? Если да — отправляет сразу, но потом анализирует заголовки ответа. 2. Сложный? Сначала улетает OPTIONS (preflight), сервер должен ответить 204 (или 200) с корректными Access-Control-Allow-*. Без них браузер даже не выполнит основной запрос — ты увидишь ошибку CORS в консоли.
Даже если ты откроешь вкладку Network в DevTools и увидишь статус 200 и тело ответа, JavaScript этого ответа не получит — браузер скроет его из соображений безопасности. Именно поэтому ошибка CORS выглядит так обманчиво: «сервер отвечает, но скрипту нельзя».
🕵️♂️ Как тестировать и отлаживать такое QA?
· Не полагайся на один Postman для кросс-доменных сценариев. Если клиент — браузер, тестируй в браузере, проверяй вкладку Console + Network. · Смотри на preflight-запрос (OPTIONS) и его ответ: есть ли там Access-Control-Allow-Origin, Access-Control-Allow-Headers, Access-Control-Allow-Methods. Если сервер их не отдаёт — это корень проблемы. · Убедись, что сервер настроен корректно: · Access-Control-Allow-Origin указывает конкретный origin (или *, но тогда нельзя с credentials) · При использовании кук/авторизационных заголовков нужен Access-Control-Allow-Credentials: true · В preflight должны быть перечислены все нестандартные заголовки, которые шлёт клиент. · Для быстрых проверок можно использовать прокси (например, CORS Anywhere), но помни: продакшен-решение — настройка сервера, а не хаки.