I'm trying to POST a JSON object using fetch.
From what I can understand, I need to attach a stringified object to the body of the request, e.g.:
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) })
When using jsfiddle's json echo I'd expect to see the object I've sent ({a: 1, b: 2}
) back, but this does not happen - chrome devtools doesn't even show the JSON as part of the request, which means that it's not being sent.
This question is related to
javascript
json
fetch-api
After spending some times, reverse engineering jsFiddle, trying to generate payload - there is an effect.
Please take eye (care) on line return response.json();
where response is not a response - it is promise.
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
I think that, we don't need parse the JSON object into a string, if the remote server accepts json into they request, just run:
const request = await fetch ('/echo/json', {
headers: {
'Content-type': 'application/json'
},
method: 'POST',
body: { a: 1, b: 2 }
});
Such as the curl request
curl -v -X POST -H 'Content-Type: application/json' -d '@data.json' '/echo/json'
In case to the remote serve not accept a json file as the body, just send a dataForm:
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
});
Such as the curl request
curl -v -X POST -H 'Content-type: application/x-www-form-urlencoded' -d '@data.txt' '/echo/form'
From search engines, I ended up on this topic for non-json posting data with fetch, so thought I would add this.
For non-json you don't have to use form data. You can simply set the Content-Type
header to application/x-www-form-urlencoded
and use a string:
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'
});
An alternative way to build that body
string, rather then typing it out as I did above, is to use libraries. For instance the stringify
function from query-string
or qs
packages. So using this it would look like:
import queryString from 'query-string'; // import the queryString class
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: queryString.stringify({for:'bar', blah:1}) //use the stringify object of the queryString class
});
I think your issue is jsfiddle
can process form-urlencoded
request only.
But correct way to make json request is pass correct json
as a body:
fetch('https://httpbin.org/post', {_x000D_
method: 'post',_x000D_
headers: {_x000D_
'Accept': 'application/json, text/plain, */*',_x000D_
'Content-Type': 'application/json'_x000D_
},_x000D_
body: JSON.stringify({a: 7, str: 'Some string: &=&'})_x000D_
}).then(res=>res.json())_x000D_
.then(res => console.log(res));
_x000D_
You only need to check if response is ok coz the call not returning anything.
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((response) => {if(response.ok){alert("the call works ok")}})
.catch (function (error) {
console.log('Request failed', error);
});
This is related to Content-Type
. As you might have noticed from other discussions and answers to this question some people were able to solve it by setting Content-Type: 'application/json'
. Unfortunately in my case it didn't work, my POST request was still empty on the server side.
However, if you try with jQuery's $.post()
and it's working, the reason is probably because of jQuery using Content-Type: 'x-www-form-urlencoded'
instead of 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'}
})
I have created a thin wrapper around fetch() with many improvements if you are using a purely 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);
});
To use it you have the variable api
and 4 methods:
api.get('/todo').then(all => { /* ... */ });
And within an async
function:
const all = await api.get('/todo');
// ...
Example with 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');
});
If your JSON payload contains arrays and nested objects, I would use URLSearchParams
and jQuery's param()
method.
fetch('/somewhere', {
method: 'POST',
body: new URLSearchParams($.param(payload))
})
To your server, this will look like a standard HTML <form>
being POST
ed.
It might be useful to somebody:
I was having the issue that formdata was not being sent for my request
In my case it was a combination of following headers that were also causing the issue and the wrong Content-Type.
So I was sending these two headers with the request and it wasn't sending the formdata when I removed the headers that worked.
"X-Prototype-Version" : "1.6.1", "X-Requested-With" : "XMLHttpRequest"
Also as other answers suggest that the Content-Type header needs to be correct.
For my request the correct Content-Type header was:
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
So bottom line if your formdata is not being attached to the Request then it could potentially be your headers. Try bringing your headers to a minimum and then try adding them one by one to see if your problem is rsolved.
you can use fill-fetch, which is an extension of fetch
. Simply, you can post data as below:
import { fill } from 'fill-fetch';
const fetcher = fill();
fetcher.config.timeout = 3000;
fetcher.config.maxConcurrence = 10;
fetcher.config.baseURL = 'http://www.github.com';
const res = await fetcher.post('/', { a: 1 }, {
headers: {
'bearer': '1234'
}
});
Had the same issue - no body
was sent from a client to a server.
Adding Content-Type
header solved it for me:
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 => {
...
})
The top answer doesn't work for PHP7, because it has wrong encoding, but I could figure the right encoding out with the other answers. This code also sends authentication cookies, which you probably want when dealing with e.g. PHP forums:
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);
});
}
Source: Stackoverflow.com