Fetch: POST JSON data
Я пытаюсь опубликовать объект JSON с помощью fetch.
из того, что я могу понять, мне нужно прикрепить строковый объект к телу запроса, например:
fetch("/echo/json/",
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify({a: 1, b: 2})
})
.then(function(res){ console.log(res) })
.catch(function(res){ console.log(res) })
при использовании JSON echo jsfiddle Я ожидал бы увидеть объект, который я послал ({a: 1, b: 2}) назад, но этого не происходит - chrome devtools даже не показывает JSON как часть запроса, что означает, что он не отправляется.
11 ответов:
С ES2017
async/awaitподдержка это какPOSTполезная нагрузка JSON:(async () => { const rawResponse = await fetch('https://httpbin.org/post', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({a: 1, b: 'Textual content'}) }); const content = await rawResponse.json(); console.log(content); })();не может использовать ES2017? См. @vp_art по ответ с помощью обещаний
вопрос, однако, задает вопрос, вызванный давно Исправлена ошибка chrome.
Оригинальный ответ следует.chrome devtools даже не показывает JSON как часть запрос
это реальная проблема здесь и ошибка с chrome devtools, исправлено в Chrome 46.
этот код отлично работает - он правильно отправляет JSON, его просто нельзя увидеть.
Я ожидал бы увидеть объект, который я отправил обратно
это не работает, потому что это не правильный формат для Эха JSfiddle.
The исправить код - это:
var payload = { a: 1, b: 2 }; var data = new FormData(); data.append( "json", JSON.stringify( payload ) ); fetch("/echo/json/", { method: "POST", body: data }) .then(function(res){ return res.json(); }) .then(function(data){ alert( JSON.stringify( data ) ) })для конечных точек, принимающих полезную нагрузку JSON,исходный код правильный
Я думаю, что ваша проблема
jsfiddleможет процессform-urlencodedзапрос только.но правильный способ сделать запрос json-это пройти правильно
jsonкак орган:fetch('https://httpbin.org/post', { method: 'post', headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, body: JSON.stringify({a: 7, str: 'Some string: &=&'}) }).then(res=>res.json()) .then(res => console.log(res));
из поисковых систем я попал в эту тему для публикации данных без json с помощью fetch, поэтому подумал, что добавлю это.
на non-json вам не нужно использовать данные формы. Вы можете просто установить
Content-Typeзаголовокapplication/x-www-form-urlencodedи использовать строку:fetch('url here', { method: 'POST', headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work body: 'foo=bar&blah=1' });альтернативный способ построить это
bodyстрока, а не вводить его, как я сделал выше, чтобы использовать библиотеки. Например,
потратив несколько раз, обратный инжиниринг jsFiddle, пытаясь генерировать полезную нагрузку-есть эффект.
Пожалуйста, обратите внимание (уход) на линии
return response.json();где ответ не является ответом-это обещание.var json = { json: JSON.stringify({ a: 1, b: 2 }), delay: 3 }; fetch('/echo/json/', { method: 'post', headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, body: 'json=' + encodeURIComponent(JSON.stringify(json.json)) + '&delay=' + json.delay }) .then(function (response) { return response.json(); }) .then(function (result) { alert(result); }) .catch (function (error) { console.log('Request failed', error); });jsFiddle:http://jsfiddle.net/egxt6cpz/46/ & & Firefox > 39 & & Chrome > 42
Я создал тонкую обертку вокруг fetch () со многими улучшениями, если вы используете чисто JSON REST API:
// Small library to improve on fetch() usage const api = function(method, url, data, headers = {}){ return fetch(url, { method: method.toUpperCase(), body: JSON.stringify(data), // send it as stringified json credentials: api.credentials, // to keep the session on the request headers: Object.assign({}, api.headers, headers) // extend the headers }).then(res => res.ok ? res.json() : Promise.reject(res)); }; // Defaults that can be globally overwritten api.credentials = 'include'; api.headers = { 'csrf-token': window.csrf || '', // only if globally set, otherwise ignored 'Accept': 'application/json', // receive json 'Content-Type': 'application/json' // send json }; // Convenient methods ['get', 'post', 'put', 'delete'].forEach(method => { api[method] = api.bind(null, method); });, чтобы использовать его у вас есть переменная
apiи 4 методов:api.get('/todo').then(all => { /* ... */ });и
asyncфункция:const all = await api.get('/todo'); // ...пример с jQuery:
$('.like').on('click', async e => { const id = 123; // Get it however it is better suited await api.put(`/like/${id}`, { like: true }); // Whatever: $(e.target).addClass('active dislike').removeClass('like'); });
была та же проблема - нет
bodyбыл отправлен с клиента на сервер.добавлять
Content-Typeзаголовок решил это за меня:var headers = new Headers(); headers.append('Accept', 'application/json'); // This one is enough for GET requests headers.append('Content-Type', 'application/json'); // This one sends body return fetch('/some/endpoint', { method: 'POST', mode: 'same-origin', credentials: 'include', redirect: 'follow', headers: headers, body: JSON.stringify({ name: 'John', surname: 'Doe' }), }).then(resp => { ... }).catch(err => { ... })
это связано с
Content-Type. Как вы могли заметить из других обсуждений и ответов на этот вопрос, некоторые люди смогли решить его, установивContent-Type: 'application/json'. К сожалению, в моем случае это не сработало, мой запрос POST все еще был пуст на стороне сервера.однако, если вы попробуете с jQuery
$.post()и это работает, причина, вероятно, из - за jQuery с помощьюContent-Type: 'x-www-form-urlencoded'вместоapplication/json.data = Object.keys(data).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])).join('&') fetch('/api/', { method: 'post', credentials: "include", body: data, headers: {'Content-Type': 'application/x-www-form-urlencoded'} })
Это может быть полезно кому-то:
У меня была проблема, что formdata не был отправлен для моего запроса
в моем случае это была комбинация следующих заголовков, которые также вызывали проблему и неправильный тип контента.
поэтому я отправлял эти два заголовка с запросом, и он не отправлял formdata, когда я удалял заголовки, которые работали.
"X-Prototype-Version" : "1.6.1", "X-Requested-With" : "XMLHttpRequest"также как и другие ответы свидетельствуют, что Заголовок типа контента должен быть правильным.
для моего запроса правильный заголовок Content-Type был:
"Content-Type": "application / x-www-form-urlencoded; charset=UTF-8"
Итак, если ваши formdata не прикрепляются к запросу, то это могут быть ваши заголовки. Попробуйте свести ваши заголовки к минимуму, а затем попробуйте добавить их один за другим, чтобы увидеть, если ваша проблема решена.
верхний ответ не работает для PHP7, потому что он имеет неправильную кодировку, но я мог бы выяснить правильную кодировку с другими ответами. Этот код также отправляет файлы cookie аутентификации, которые вы, вероятно, хотите, когда имеете дело, например, с форумами PHP:
julia = function(juliacode) { fetch('julia.php', { method: "POST", credentials: "include", // send cookies headers: { 'Accept': 'application/json, text/plain, */*', //'Content-Type': 'application/json' "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" // otherwise $_POST is empty }, body: "juliacode=" + encodeURIComponent(juliacode) }) .then(function(response) { return response.json(); // .text(); }) .then(function(myJson) { console.log(myJson); }); }
если ваша полезная нагрузка JSON содержит массивы и вложенные объекты, я бы использовал
URLSearchParamsи jQueryparam()метод.fetch('/somewhere', { method: 'POST', body: new URLSearchParams($.param(payload)) })для вашего сервера это будет выглядеть как стандартный HTML
<form>будучиPOSTed.
Я думаю, что нам не нужно разбирать объект JSON в строку, если удаленный сервер принимает json в их запрос, просто запустите:
const request = await fetch ('/echo/json', { headers: { 'Content-type': 'application/json' }, method: 'POST', body: { a: 1, b: 2 } });как запрос скручивания
curl -v -X POST -H 'Content-Type: application/json' -d '@data.json' '/echo/json'в случае, если удаленная служба не принимает файл json в качестве тела, просто отправьте форму данных:
const data = new FormData (); data.append ('a', 1); data.append ('b', 2); const request = await fetch ('/echo/form', { headers: { 'Content-type': 'application/x-www-form-urlencoded' }, method: 'POST', body: data });как запрос скручивания
curl -v -X POST -H 'Content-type: application/x-www-form-urlencoded' -d '@data.txt' '/echo/form'
Comments