I used the example provided on the readme file.
fetch('/users', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
})
I got the following headers on devtools. The problem is marked with a "//" comment. content type is really not allowing us to set it to application/json, I have tried a 100 different ways.
As result I set up a simple node js server to see request.body (always is empty)
If I use curl http://localhost:3001/log -H 'Content-Type: application/json' -d '{"longUrl": "http://www.google.com/"}' this works fine. I can see the request.body
===
Request URL:http://localhost:3001/log
Request Method:POST
Status Code:200 OK
Remote Address:[::1]:3001
Response Headers
===
Connection:keep-alive
Content-Length:16
Content-Type:application/json; charset=utf-8
Date:Mon, 18 Apr 2016 10:04:14 GMT
ETag:W/"10-c2PoX+nt7m8FOksxlYjAhg"
X-Powered-By:Express
Request Headers
===
accept:application/json
Accept-Encoding:gzip, deflate
Accept-Language:en-GB,en;q=0.8,sq;q=0.6,it;q=0.4
Cache-Control:no-cache
Connection:keep-alive
Content-Length:32
content-type:text/plain;charset=UTF-8 //the problem//
Host:localhost:3001
Origin:http://xxxxxxxxxxxxxxx.co.uk
Pragma:no-cache
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
Request Payload
===
{name: "Hubot", login: "hubot"}
login
:
"hubot"
name
:
"Hubot"
That's really weird. You should be to set a content-type. However, since you're using Chrome 49, you're not using this polyfill at all, since Chrome has its own native implementation of fetch(). Therefore, you need to take it with the Chromium bug tracker if you believe that nothing in your application might be messing this up.
But I really doubt that there is a browser bug, since the whole GitHub.com would be broken by now due to our heavy usage of fetch with JSON data. Here's what I get when I try the same POST:
accept:application/json
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8,hr;q=0.6
Connection:keep-alive
Content-Length:32
content-type:application/json
Host:github.com
Origin:https://github.com
Referer:https://github.com/github/fetch/issues/318
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36
So it must be something in your application. Maybe some plugin that overrides window.fetch?
Oh, Ok, Sorry that does make sense :) thanks.
On another naive question, on the example above,
fetch('/users', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
})
Why are we saying 'Content-Type': 'application/json' and at the same time use JSON.stringify
I mean what is the point? shouldn't it be text/json if we are passing a string, if we are passing a json object it should be as an object? or is it the opposite true?
A JavaScript object is not a valid body value, so we need to convert the object to a String with JSON.stringify first.
There is no text/json content type. Only application/json is specified.
Why are we saying
'Content-Type': 'application/json'and at the same time useJSON.stringify
That's a good question, and @dgraham answered it well. Also, see it from our own documentation.
The short: if you supply a String, which is most of the time, you must supply an explicit content-type as well (unless you want text/plain).
hmmm, I guess the word application threw me off a bit :) I thought it was my ignorance (lack of knowledge on the subject), but now I know. Thanks
Hey Guys.
I'm using Chrome 51 and I'm getting the exact same issue posted by @valtido .
Any of you guys could get this working on your project?
I'm getting the exact same issue too. I can't find any answer.
I post a question about this on http://stackoverflow.com/questions/39689386/fetch-post-json-data-application-json-change-to-text-plain
@bo3en, the problem is that when you work in 'mode' 'no-cors', the Headers become an immutable and you will not be able to change some of its entries. One of the heads you can't change is the Content-Type. When you set 'mode' to 'no-cors' you will be able to change only these headers:
AcceptAccept-LanguageContent-LanguageContent-Type and whose value, once parsed, has a MIME type (ignoring parameters) that is application/x-www-form-urlencoded, multipart/form-data, or text/plainIn another words, in 'mode' '-no-'cors' you can only set application/x-www-form-urlencoded, multipart/form-data, or text/plain to the Content-Type.
So the solution is stop using fetch or changing it to 'cors' 'mode'. Of course this will only works if your server also accepts 'cors' requests.
Here is an example of how you could enable CORS in an Apache Server
SetEnvIfNoCase Access-Control-Request-Method "(GET|POST|PUT|DELETE|OPTIONS)" IsPreflight=1
SetEnvIfNoCase Origin ".*" AccessControlAllowOrigin=$0
SetEnvIfNoCase Origin "https://(url1.com|url2.com)$" AccessControlAllowOrigin=$0
Header always set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" env=IsPreflight
Header always set Access-Control-Allow-Headers "Content-Type, Authorization, Accept, Accept-Language" env=IsPreflight
Header always set Access-Control-Max-Age "7200" env=IsPreflight
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteCond %{ENV:IsPreflight} 1
RewriteRule ^(.*)$ $1 [R=204,L]
The above code will inject the CORS headers in the response when its necessary.
With this code your server will allow CORS only from the the domains "url1.com" or "url2.com".
Here are some references
In package.json file add field eg:-
"proxy":"http://#####.!@#"
Just set your mode to cors.
I am still getting issue on using fetch call. It is changing "Content-Type" from 'application/json' to 'text/plain;charset=UTF-8' while i run this code. If someone faced same kind of issue.


Most helpful comment
@bo3en, the problem is that when you work in 'mode' 'no-cors', the Headers become an immutable and you will not be able to change some of its entries. One of the heads you can't change is the Content-Type. When you set 'mode' to 'no-cors' you will be able to change only these headers:
AcceptAccept-LanguageContent-LanguageContent-Typeand whose value, once parsed, has a MIME type (ignoring parameters) that isapplication/x-www-form-urlencoded,multipart/form-data, ortext/plainIn another words, in 'mode' '-no-'cors' you can only set
application/x-www-form-urlencoded,multipart/form-data, ortext/plainto theContent-Type.So the solution is stop using fetch or changing it to 'cors' 'mode'. Of course this will only works if your server also accepts 'cors' requests.
Here is an example of how you could enable CORS in an Apache Server
The above code will inject the CORS headers in the response when its necessary.
With this code your server will allow CORS only from the the domains "url1.com" or "url2.com".
Here are some references