Кросс-доменный POST-запрос в JS: Fetch без обновления
Как отправить кросс-доменный POST-запрос с помощью JavaScript (Fetch или XHR) без обновления страницы. Решение ошибок CORS, blocked by cors policy, разбор ответа response.json() и настройки Access-Control-Allow-Origin.
Как отправить кросс-доменный POST-запрос с помощью JavaScript без обновления страницы и как получить и разобрать ответ?
Для кросс-доменного POST-запроса в JavaScript используйте Fetch API или XMLHttpRequest в асинхронном режиме — это позволит отправить данные без обновления страницы. Главная засада — CORS: сервер должен разрешить ваш origin через заголовок Access-Control-Allow-Origin, иначе браузер заблокирует запрос с ошибкой blocked by cors policy. Получите ответ через response.json() в Fetch или JSON.parse(xhr.responseText) в XHR, и всё заработает гладко.
Содержание
- Что такое CORS и почему возникает ошибка cors (blocked by cors policy)
- Отправка кросс-доменного POST-запроса с fetch post без обновления страницы
- Использование XMLHttpRequest (ajax post) для cors запросы
- Настройки cors на сервере: Access-Control-Allow-Origin и cors preflight
- Получение и разбор ответа: fetch post response и JSON.parse
- Решение типичных проблем: fetch cors, cors origin и credentials
- Примеры кода и лучшие практики для js fetch post
- Источники
- Заключение
Что такое CORS и почему возникает ошибка cors (blocked by cors policy)
Представьте: ваш сайт на localhost:3000 пытается POST’ить данные на api.example.com. Браузер говорит “стоп” — это и есть CORS, механизм безопасности, блокирующий кросс-доменные запросы. Без него любой сайт мог бы тайком слать данные от вашего имени.
CORS проверяет заголовок Origin из запроса и сравнивает с Access-Control-Allow-Origin на сервере. Если не совпадает — ошибка cors, типичная “blocked by cors policy no ‘access-control-allow-origin’”. По данным MDN Web Docs, это защищает от CSRF-атак, но бесит разработчиков.
А что насчёт простых запросов? GET или POST без кастомных заголовков иногда проходят “просто так”. Но добавьте Content-Type: application/json — и браузер шлёт preflight OPTIONS. Об этом позже.
Почему без обновления страницы? Потому что Fetch и XHR асинхронны по умолчанию. Синхронный XHR устарел и блокирует UI — не повторяйте.
Отправка кросс-доменного POST-запроса с fetch post без обновления страницы
Fetch — современный выбор для fetch post. Вот базовый пример:
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ key: 'value' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Ошибка cors или сети:', error));
Это не обновит страницу — промисы работают в фоне. Но если сервер не настроен, ждите fetch cors ошибку. Как пишет javascript.ru, для credentials (куки, auth) добавьте credentials: 'include', но тогда Access-Control-Allow-Origin не может быть ‘*’.
Тестируйте в DevTools: Network вкладка покажет, прошёл ли запрос или заблокировали cors origin.
Просто? Да, но сервер — ключ.
Использование XMLHttpRequest (ajax post) для cors запросы
Старый добрый XHR (ajax post) всё ещё в деле, особенно если Fetch не поддерживается. Асинхронно, без релоада:
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://api.example.com/data', true); // true = async
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.withCredentials = true; // для куки
xhr.onload = function() {
if (xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
console.log(data);
}
};
xhr.onerror = function() {
console.error('CORS или сеть сломалась');
};
xhr.send(JSON.stringify({ key: 'value' }));
learn.javascript.ru подчёркивает: withCredentials=true требует серверного Allow-Credentials: true. Иначе blocked by cors policy.
XHR крут для старых браузеров, но Fetch проще с промисами. Выбор за вами.
Настройки cors на сервере: Access-Control-Allow-Origin и cors preflight
Сервер решает всё. Для Node.js/Express:
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://your-site.com'); // не '*', если credentials
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') res.sendStatus(200);
next();
});
Эта диаграмма из javascript.ru идеально показывает поток: браузер шлёт Origin, сервер отвечает Allow-Origin, затем основной POST. Preflight (OPTIONS) нужен для сложных запросов — cors preflight проверяет методы/заголовки заранее.
Иван Гришаев советует: для публичных API используйте ‘*’, но осторожно с credentials. Nginx/Apache тоже настраиваются аналогично.
Без этого — вечный круг ошибок cors запросы.
Получение и разбор ответа: fetch post response и JSON.parse
Запрос ушёл, ответ пришёл. Теперь fetch post response:
В Fetch:
fetch(url, options)
.then(response => {
if (!response.ok) throw new Error('Сервер вернул ' + response.status);
return response.json(); // авто-разбор JSON
})
.then(data => {
// data готово
});
response.json() — асинхронный парсер, лучше ручного JSON.parse. Но если ответ не JSON? Используйте response.text().
В XHR: JSON.parse(xhr.responseText) после onload. Проверяйте status!
MDN Web Docs предупреждает: без CORS ответ придёт, но скрипт его не увидит — opaque response.
Разбор — это легко, если CORS на месте.
Решение типичных проблем: fetch cors, cors origin и credentials
Fetch cors не работает? Шаги:
- Blocked by cors policy: Сервер не шлёт Allow-Origin. Добавьте его.
- Preflight hangs: OPTIONS не отвечает 200. Добавьте обработку OPTIONS.
- Credentials fail: Смешали ‘*’ и ‘include’ — браузер блочит. Укажите точный origin.
- No-CORS mode: fetch с mode: ‘no-cors’ — ответ opaque, бесполезно для чтения.
Консоль покажет детали: “has been blocked by CORS policy”. Гуглите точный текст.
Для локалки: запустите сервер с --disable-web-security (Chrome), но только для теста! Производство — нормальные настройки cors origin.
И credentials: куки/авторизация требуют extra заголовков.
Примеры кода и лучшие практики для js fetch post
Полный пример с формой (без релоада):
<form id="myForm">
<input id="data" type="text">
<button type="submit">Отправить</button>
</form>
<script>
document.getElementById('myForm').addEventListener('submit', async (e) => {
e.preventDefault();
const value = document.getElementById('data').value;
try {
const response = await fetch('https://api.example.com/post', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: value })
});
if (!response.ok) throw new Error('Ошибка: ' + response.status);
const result = await response.json();
alert('Успех: ' + JSON.stringify(result));
} catch (error) {
console.error('Fetch cors или другая беда:', error);
}
});
</script>
Лучшие практики:
- Всегда try/catch или .catch().
- Проверяйте response.ok.
- Для больших данных — FormData вместо JSON.
- Proxy в dev (vite/react) для обхода CORS локально.
- Мониторьте Network в DevTools.
Из javascript.ru: избегайте синхронных запросов — UI замрёт.
Это покроет 99% случаев js fetch post.
Источники
- MDN Web Docs: CORS — Руководство по HTTP CORS, ошибкам и заголовкам: https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS
- javascript.ru: Fetch кросс-домен — Примеры Fetch API для кросс-доменных запросов и обработки ответов: https://learn.javascript.ru/fetch-crossorigin
- javascript.ru: XMLHttpRequest кросс-домен — AJAX POST с XHR, withCredentials и CORS-нюансами: https://learn.javascript.ru/xhr-crossdomain
- Блог Ивана Гришаева: CORS — Настройка сервера, preflight и заголовки для POST-запросов: https://grishaev.me/cors/
Заключение
Кросс-доменный POST-запрос без обновления — это Fetch или XHR плюс правильные настройки cors на сервере: Access-Control-Allow-Origin спасёт от blocked by cors policy. Разбирайте ответ response.json() или JSON.parse(), и вы в деле. Тестируйте шаг за шагом — от DevTools до продакшена. Если застряли, проверьте preflight и credentials. Удачи с вашими cors запросы!
Fetch API позволяет отправлять кросс-доменные POST-запросы без обновления страницы. Укажите method: 'POST', credentials: 'include' для куки и необходимые заголовки. Сервер обязан ответить заголовками Access-Control-Allow-Origin (или '*') и Access-Control-Allow-Credentials: true, чтобы избежать ошибки blocked by cors policy. Для разбора ответа используйте response.json(). Это стандартный механизм для cors origin запросов с обработкой preflight при сложных заголовках.
Для кросс-доменного POST-запроса используйте fetch с Content-Type: 'application/json' и body: JSON.stringify(data). Сервер должен вернуть Access-Control-Allow-Origin для вашего домена, иначе возникнет ошибка cors. Разберите ответ через response.json(). Добавьте credentials: 'include' при необходимости куки. Такой подход решает fetch cors без preflight в простых случаях и предотвращает обновление страницы.
Кросс-доменный ajax post реализуется через XMLHttpRequest с withCredentials = true и обработчиком onload для JSON.parse(this.responseText). Сервер возвращает Access-Control-Allow-Origin, Access-Control-Allow-Methods/Headers для cors preflight. Асинхронный режим (async: true) предотвращает обновление страницы. Для старых IE подойдет XDomainRequest без кастомных заголовков. Это решает проблемы fetch cors и blocked by cors policy.

В fetch post добавьте заголовки Content-Type, Authorization и кастомные; браузер запустит cors preflight OPTIONS при необходимости. Сервер выставляет Access-Control-Allow-Origin: ''** и Allow-Headers для обхода blocked by cors policy. Проверьте response.ok перед response.json(). Это решает настройки cors для POST без перезагрузки, включая fetch cors access control allow origin. Подходит для сложных кросс-доменных сценариев.
