fetch: Getting cookies from fetch response - express

I'm trying to implement client login using fetch on react.
I'm using passport for authentication. The reason I'm using fetch and not regular form.submit(), is because I want to be able to recieve error messages from my express server, like: "username or password is wrong".
I know that passport can send back messages using flash messages, but flash requires sessions and I would like to avoid them.
This is my code:
fetch('/login/local', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
}).then(res => {
console.log(res.headers.get('set-cookie')); // undefined
console.log(document.cookie); // nope
return res.json();
}).then(json => {
if (json.success) {
this.setState({ error: '' });
this.context.router.push(json.redirect);
}
else {
this.setState({ error: json.error });
}
});
The server sends the cookies just fine, as you can see on chrome's dev tools:
But chrome doesn't set the cookies, in Application -> Cookies -> localhost:8080: "The site has no cookies".
Any idea how to make it work?

The problem turned out to be with the fetch option credentials: same-origin/include not being set.
As the fetch documentation mentions this option to be required for sending cookies on the request, it failed to mention this when reading a cookie.
So I just changed my code to be like this:
fetch('/login/local', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
credentials: 'same-origin',
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
}).then(res => {
return res.json();
}).then(json => {
if (json.success) {
this.setState({ error: '' });
this.context.router.push(json.redirect);
}
else {
this.setState({ error: json.error });
}
});

From Differences from jQuery section of the Fetch API on Mozilla:
fetch() won't receive cross-site cookies. You can’t establish a cross
site session using fetch(). Set-Cookie headers from other sites are
silently ignored.
fetch() won’t send cookies, unless you set the
credentials init option. Since Aug 25, 2017: The spec changed the
default credentials policy to same-origin. Firefox changed since
61.0b13.)

I spent a long time but nothing worked for me.
after trying several solutions online this one worked for me.
Hopefully it will work for you too.
{
method: "POST",
headers: {
"content-type": "API-Key",
},
credentials: "include",
}

I had to include credentials: 'include' in the fetch options:
fetch('...', {
...
credentials: 'include', // Need to add this header.
});

Related

Problem put axios update user Strapi and NuxtJS

I have a problem with the right in strapi.
I create user with the role Authenticated and try modified the data with axios.
But it is impossible has modified because return forbidden. I look if the user has right, Update is check in role authenticated.
If i check update in role public, my modification with axios is ok. Why ? I don't undestand the problem.
My code for send
.put(
`https://localhost:4000/users/${this.data.id}`,
{
headers: {
Authorization: `Bearer ${token}`
},
Nom: 'JEAN'
}
)
.then((res) => {
// Handle success.
console.log(res)
})
.catch((error) => {
// Handle error.
console.error('An error occurred:', error)
})```
Thank you
I'm not sure the axios request has the right format.
According to this documentation - https://github.com/axios/axios#axiosconfig
This probably should look like this:
axios({
method: 'put',
url: `https://localhost:4000/users/${this.data.id}`,
data: {
username: 'JEAN'
},
headers: {
Authorization: `Bearer ${token}`
}
});

how to use axios to send data to line notify

I tried to send data to line notify server by axios and it fail
I have tried 2 version of code. as shown below
version 1 :
axios({
method: "post",
url: "https://notify-api.line.me/api/notify",
data: 'message="from vue"',
config: {
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "multipart/form-data"
}
},
Authorization: "Bearer [my token]"
})
.then(function(response) {
console.log(response);
})
.catch(function(response) {
console.log(response);
});
response is
XMLHttpRequest cannot load https://notify-api.line.me/api/notify due to access control checks.
Error: Network Error
and version 2 is :
axios
.post("https://notify-api.line.me/api/notify", "message=from vue", {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Bearer [my token]"
}
})
.then(response => {
console.log(response);
});
response is
Preflight response is not successful
XMLHttpRequest cannot load https://notify-api.line.me/api/notify due to access control checks.
Error: Network Error
What wrong with is
but I have tried in postman it work fine
Oh I am too familiar with this. Heres an explanation on stackoverflow as to why your request works with postman but not in browser. Long story short browsers send a preflight options check that will ask the server if the action you're about to perform is allowed. Postman does not. Usually the "Access-Control-Allow-Origin": "*" header is sent by the server to the browser not the other way around.
Inside the docs for LINE Notify you can find:
POST https://notify-api.line.me/api/notify
Sends notifications to users or groups that are related to an access token.
If this API receives a status code 401 when called, the access token will be deactivated on LINE Notify (disabled by the user in most cases). Connected services will also delete the connection information.
Requests use POST method with application/x-www-form-urlencoded (Identical to the default HTML form transfer type).
My guess is that your access_token might have been deactivated. Try requiring a new access token and doing the request again.
I think it is impossible to connect directly to the external url for the axios cuz ajax is basically for the inner data network. But you might have a controller if you do a web project, so you can just use your controller language to make a connection with line notify. In my case, I made a rails project and used axios in the vue.js, so I made a link like this.
View(axios) => Controller(Ruby) => LineAPI
me currently work on this too.
I did my app with node js.
My way below is for your reference, it works well.
const axios = require('axios');
const querystring = require('querystring');
axios({
method: 'post',
url: 'https://notify-api.line.me/api/notify',
headers: {
'Authorization': 'Bearer ' + 'YOUR_ACCESS_TOKEN',
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*'
},
data: querystring.stringify({
message: 'something you would like to push',
})
})
.then( function(res) {
console.log(res.data);
})
.catch( function(err) {
console.error(err);
});
I try it works.
async function test() {
const result = await axios({
method: "post",
url: "https://notify-api.line.me/api/notify",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer [token]",
},
data: 'message=你好哇'
})
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
}
test();
I think you can check response on chrome debugger network.
or provide more information, thx.

How to check if body in fetch POST has sent to API in react native?

I am building a react native app and got this following error. I want to send inputted message, email, and name to API, but it's not showing any result in API.
Here is the code:
fetch('localserverusingIPaddress', {
method: 'POST',
headers: {
"Content-Type": "application/json",
'Accept': 'application/json',
},
body: JSON.stringify({
name: this.state.name,
email: this.state.email,
message: this.state.message,
}),
})
.then((response)=> {console.warn(response.json())})
//{
// if (response.status){
// return response.json();
// }
// console.warn(response.json())
// return response.json();
//})
//console.warn(response);
//response.json()
//console.warn(JSON.parse(response))})
.then((responseData)=>{
this.showAlert();
console.warn(responseData);
return responseData;
})
.catch((error) => {
console.warn(error);
});
However, when I try to check the inputted texts in iOS
simulator, it's showing the value. It's also showing the values when I post data to API directly with postman. So I start to think that the body was failed to pass to API.
Can anyone please tell me why is this happening and how to fix this? Thank you so much, I'm facing this problem for several weeks...
First step is to make sure if your iOS simulator is actually able to make requests to your localhost or not. If it can't reach your local network, it must throw some kind of connectivity error. However, from your comment above, it seems that is not an issue.
Try this code:
let url = 'localserverusingIPaddress';
let requestObject = {
name: this.state.name,
email: this.state.email,
message: this.state.message
};
try {
let response = await fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(requestObject)
});
responseJson = await response.json();
console.log(responseJson);
} catch (error) {
console.error(error);
}
Try this and see what is the logged output.
Easiest way to see if the request has actually reached your API is from the API end itself. Your server must have some sort of event logging implemented. See what happens there when you make a request from Postman and compare its output with what happens when you make a request from the app.

How to send data to server and fetched response using react native application?

I am trying to learn react native application by making a simple login page using api call. Where I will send user name and password to api and it will give me response. But I can't do it. Well I am sharing my code here.....
var myRequest = new Request('<my API >', {method: 'POST', body: '{"username":this.state.uName , "password":this.state.pwd}'});
fetch(myRequest).then(function(response) {
alert('Res'+response);
}).then(function(response) {
alert('Blank'+response);
})
.catch(function(error) {
alert('Error'+error);
});
I think the way of passing my user name and password to server is wrong. Please give me some idea then I can understand what is wrong here.
var data = {
"username": this.state.username,
"password": this.state.password
}
fetch("https://....", {
method: "POST",
headers: headers,
body: JSON.stringify(data)
})
.then(function(response){
return response.json();
})
.then(function(data){
console.log(data)
});
I hope this helps.
You need to Stringify the json data to send request as Post method with Json parameters as you are trying to do...
Here is the example code for how to encode data before requesting for response
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
Here is the sample code for login :
fetch(<hostURL>, {
method: 'POST',
headers: { 'Accept': 'application/json','Content-Type': 'application/json',},
body: JSON.stringify({ userName: <userName> ,Password: <Password>,})
}).then((response) => response.json())
.then((responseData) => {
console.log(responseData);
}).catch((error) => {
console.log("Error");
});
As the commentators before me stated, you simply need to stringify your JSON Body. In general, I' suggest that you incorporate e.g. api sauce into you stack. It is a comprehensive wrapper around the axios library, providing standardized errors and an ok key for quick checks.

How do i get the status of my response when using fetch in react-native?

I am making Log In page for my react native application. My api sends different response when my username and password are valid and invalid. So I want to track and save the status of my response in some state variable and then later perform function accordingly. Please suggest me way to do that.
doSignUp() {
console.log("inside post api");
fetch('MyApiUrl', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
password: this.state.password,
email:this.state.email,
name: this.state.firstname,
last_name :this.state.last_name,
mobile:this.state.mobile,
ssn:"2222222"
})
}).then((response) => {console.log('response:',response.status);
response.json()}
.then((responseData) => {
console.log("inside responsejson");
console.log('response object:',responseData)
console.log('refresh token:',responseData[0].token.refresh_token)
console.log('access token:',responseData[0].token.access_token);
}).done();
}
As far as I understand you want to know the http status code of your fetch request.
Usually your response object includes a "status" property. So you should be able to receive the status code by using this:
response.status
In case of a successful request this will return 200.