issue with reading result from POST in fetch request to Github API - javascript

I am using the fetch api to get an access token returned from the github api.
When I check the network tab I see that the token is returned but I am unable to access it in my fetch request.
My code looks like this:
fetch(`https://github.com/login/oauth/access_token?client_id=***&client_secret=***&code=${code}&redirect_uri=http://localhost:3000/&state=react`, {
method: 'POST',
mode: 'no-cors',
headers: new Headers({
'Content-Type': 'application/json'
})
}).then(function(res) {
console.log(res); // I have already tried return res.json() here
})
The console displays the following error if I return res.json():
index.js:30 Uncaught (in promise) SyntaxError: Unexpected end of input
The GitHub docs states the response takes the following format:
By default, the response takes the following form:
access_token=e72e16c7e42f292c6912e7710c838347ae178b4a&token_type=bearer
I guess it isn't returning valid json but just a string so I am not sure how to access this response.
The response looks like this:
However, when I try and log out the response I get SyntaxError: Unexpected end of input

If you are using mode: 'no-cors, browser will restrict to access body. Browser has security for cross domain. If you want to access body you have to call without mode: 'no-cors property.
https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
This will work
fetch(`https://jsonplaceholder.typicode.com/posts/1`, {
method: 'GET',
headers: new Headers({
'Content-Type': 'application/json'
})
})
.then(res => res.json())
.then(function(res) {
console.log(res);
})
This will not work
fetch(`https://jsonplaceholder.typicode.com/posts/1`, {
method: 'GET',
mode: 'no-cors',
headers: new Headers({
'Content-Type': 'application/json'
})
})
.then(res => res.json())
.then(function(res) {
console.log(res);
})

I think you're almost there. You've mentioned this link to the docs. If you read further, you can see that to get response in JSON, you need to include a header named Accept with the value of application/json.
fetch(` ... `, {
method: 'POST',
mode: 'no-cors',
headers: new Headers({
'Content-Type': 'application/json',
'Accept': 'application/json'
})
}).then(function(res) {
...
})
This way, you can apply .json() on res.

Related

Multiple headers in REST call giving #415 error

I have this REST request that I can't seem to get to work correctly.
This is just the "login" to the resource but I assume the same problem will occur as I move forward.
var bodyinfo = {
ApiKey: "#theapikey",
Username: "#theusername",
Password: "#thepassword" };
fetch('{base-url}/user/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
mode: 'no-cors',
body: JSON.stringify(bodyinfo)
})
.then(function(response){
return response.json();
})
.then(function(data){
console.log(data)
});
I've tried to stringify the headers as well but I always end up getting 'Status Code: 415 Unsupported Media Type'.
The HTTPRequest works fine when testing with either Postman or when I run it through a HTTPRequest in WebStorm.

PHP and js fetch Unexpected token < in JSON error in localhost

I know there are a few question about this topic. I applied at them but I still get this error
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
this code works other APIs
getData() {
fetch('http://localhost:50/data', {
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then((response) => { return response.json(); })
.then((result) => {
console.log(result);
});
}
php code
header('Access-Control-Allow-Origin: *');
header('Content-type:application/json;charset=utf-8');
echo json_encode(['data' => 'test']);
That unexpected < probably means you got back HTML instead of JSON. Log the response and read it, it may be an error message from your server.
Developer Mozilla has a good guide for using fetch, especially for beginners.
I actually just faced with the same problem earlier and after searching for a few hours with no luck, so I experimented on it and finally got it working.
I copy pasted the sample codes on Developer Mozilla with the complete initialized values for the object after the url
fetch(url, {
body: JSON.stringify(data), // must match 'Content-Type' header
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, same-origin, *omit
headers: {
'user-agent': 'Mozilla/4.0 MDN Example',
'content-type': 'application/json'
},
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, cors, *same-origin
redirect: 'follow', // manual, *follow, error
referrer: 'no-referrer', // *client, no-referrer
})
.then(response => response.json())
and it worked, so I tried removing each property to see if removing it will cause the error again and I found out that removing the credentials: 'same-origin will cause the error I experienced earlier.
You forgot to put a method: 'GET' on your code. Your final code should look like this. Hope it helps.
fetch('http://localhost:50/data', {
method: 'GET',
credentials: 'same-origin',
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then((response) => { return response.json(); })
.then((result) => {
console.log(result);
});

Fetch with Credentials and Json Body

Need to send a POST request with a JSON body. I have to use fetch.
Original code snippet, which worked:
headers = {'Content-Type': 'application/json'};
body = {path: 'path1'};
fetch(url, {
method: 'post',
headers: headers,
body: JSON.stringify(body)
})
.then(response => {//do work});
Now I have to add Http-Only cookies for A&A.
This link has answer for that. Basically, have to add another parameter.
Afterwards updated code to:
fetch(url, {
credentials: 'include',
method: 'post',
headers: headers,
body: JSON.stringify(body)
})
.then(response => {//do work});
Server doesn't see cookie in header.
Then tested the fetch by removing everything else:
fetch(url, {
credentials: 'include',
method: 'post',
})
.then(response => {//do work});
A&A part works i.e. Server now sees cookie in header. So, added the body back and didn't believe it would work:
body = {path: 'path1'};
fetch(url, {
credentials: 'include',
method: 'post',
body: JSON.stringify(body)
})
.then(response => {//do work});
As expected, it didn't work. The Express server with CookieParser is showing that body is {}.
After added the Content-Type header:
body = {path: 'path1'};
fetch(url, {
credentials: 'include',
method: 'post',
headers: {'Content-Type': 'application/json'}
body: JSON.stringify(body)
})
.then(response => {//do work});
Now, the cookie has disappeared again. Guessing it's because of adding a new header, and replacing header generated by fetch, which includes cookie. Am I wrong?
While I was searching I found a similar question with no answer.
How should I proceed?

Fetch response malformed

The issue is basically that the fetch response object is not correct. Pictures to clarify the issue are below as it is hard to explain.
My fetch request code.
fetch(this.constructUrl(url), {
method: method,
mode: 'no-cors',
headers: new Headers({
'Authorization': 'Bearer ' + this.token,
'Accept': 'application/json',
'Content-Type': 'application/json',
}),
body: new FormData(document.getElementById(formIdentifier))
}).then(function (response) {
if (response.ok) {
return response.json().then(callback);
}
console.log(response);
}).catch(function(error) {
console.log(error);
});
The fetch response object.
The chrome response/request details
The chrome response data
So as you can see, the data in chrome looks correct but for some reason, the fetch response object does not seem to reflect what chrome picks up.
I had to switch 'no-cors' to 'cors' and allow cors in my rest stack.

React Native Fetch Request Fails Without CSRF Token

I've been developing a mobile complement to my web application built with Rails. Using Fetch API, I keep getting the notice "Can't verify CSRF token authenticity".
export const login = (user) => {
fetch('http://localhost:3000/api/session', {
method: 'POST',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({user})
})
// promise handling
}
Edit: Managed to get it to work but I still don't really understand why. If anyone has the same problem, this is how I resolved it. I managed to get the form_authenticity_token from my rails application and saved it as a variable that I then passed to the function. Haven't tested removing the credentials key.
export const login = (user, token) => {
return fetch('http://localhost:3000/api/session', {
method: 'POST',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ user, authenticity_token: token })
})
You need to add CSRF token in headers or disable / remove CSRF on cross domain request.
export const login = (user) => {
fetch('http://localhost:3000/api/session', {
method: 'POST',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-TOKEN': token
},
body: JSON.stringify({user})
})
// promise handling
}
When working with Django backend you should set:
'X-CSRFToken': csrf_token // not 'X-CSRF-Token' !!!
in your JS request headers.
Environment:
To set the token on the backend side, use:
{% csrf_token %} <!-- put this in your html template -->
And then, to get the token in the JS code:
const csrf_token = document.getElementsByName('csrfmiddlewaretoken')[0].value;

Categories

Resources