Веб

Кросс-доменный POST-запрос в JS: Fetch без обновления

Как отправить кросс-доменный POST-запрос с помощью JavaScript (Fetch или XHR) без обновления страницы. Решение ошибок CORS, blocked by cors policy, разбор ответа response.json() и настройки Access-Control-Allow-Origin.

5 ответов 2 просмотра

Как отправить кросс-доменный 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, и всё заработает гладко.

Диаграмма кросс-доменных запросов XMLHttpRequest с заголовками Origin и Access-Control-Allow-Origin

Содержание


Что такое 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. Вот базовый пример:

javascript
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 не поддерживается. Асинхронно, без релоада:

javascript
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:

javascript
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();
});
Диаграмма кросс-доменных запросов XMLHttpRequest с заголовками Origin и Access-Control-Allow-Origin

Эта диаграмма из javascript.ru идеально показывает поток: браузер шлёт Origin, сервер отвечает Allow-Origin, затем основной POST. Preflight (OPTIONS) нужен для сложных запросов — cors preflight проверяет методы/заголовки заранее.

Иван Гришаев советует: для публичных API используйте ‘*’, но осторожно с credentials. Nginx/Apache тоже настраиваются аналогично.

Без этого — вечный круг ошибок cors запросы.


Получение и разбор ответа: fetch post response и JSON.parse

Запрос ушёл, ответ пришёл. Теперь fetch post response:

В Fetch:

javascript
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 не работает? Шаги:

  1. Blocked by cors policy: Сервер не шлёт Allow-Origin. Добавьте его.
  2. Preflight hangs: OPTIONS не отвечает 200. Добавьте обработку OPTIONS.
  3. Credentials fail: Смешали ‘*’ и ‘include’ — браузер блочит. Укажите точный origin.
  4. 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

Полный пример с формой (без релоада):

html
<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.


Источники

  1. MDN Web Docs: CORS — Руководство по HTTP CORS, ошибкам и заголовкам: https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS
  2. javascript.ru: Fetch кросс-домен — Примеры Fetch API для кросс-доменных запросов и обработки ответов: https://learn.javascript.ru/fetch-crossorigin
  3. javascript.ru: XMLHttpRequest кросс-домен — AJAX POST с XHR, withCredentials и CORS-нюансами: https://learn.javascript.ru/xhr-crossdomain
  4. Блог Ивана Гришаева: 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 запросы!

M

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 при сложных заголовках.

Илья Кантор / Автор учебника по JavaScript

Для кросс-доменного POST-запроса используйте fetch с Content-Type: 'application/json' и body: JSON.stringify(data). Сервер должен вернуть Access-Control-Allow-Origin для вашего домена, иначе возникнет ошибка cors. Разберите ответ через response.json(). Добавьте credentials: 'include' при необходимости куки. Такой подход решает fetch cors без preflight в простых случаях и предотвращает обновление страницы.

Илья Кантор / Автор учебника по JavaScript

Кросс-доменный 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.

Диаграмма кросс-доменных запросов XMLHttpRequest с заголовками Origin и Access-Control-Allow-Origin
И

В 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. Подходит для сложных кросс-доменных сценариев.

Авторы
M
Контрибьюторы документации
Илья Кантор / Автор учебника по JavaScript
Автор учебника по JavaScript
И
Backend-инженер
Источники
MDN Web Docs / Документационный портал по веб-технологиям
Документационный портал по веб-технологиям
Проверено модерацией
Модерация
Кросс-доменный POST-запрос в JS: Fetch без обновления