Not able to get the res.json() value from nodejs server - javascript

I am using react.js as frontend and nodejs for the backend. My client-side code is
export const updatePaymentDetails = (userId, token, paymentDetails) => {
return fetch(`${API}/user/${userId}`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
},
body: JSON.stringify(paymentDetails)
})
.then(response => {
console.log(response);
return response.json();
})
.catch(err => console.log(err));
};
And My server-side code is
exports.updateUser = (req, res) => {
User.findByIdAndUpdate(
{_id: req.profile._id},
{$set: req.body},
{new: true, useFindAndModify: false},
(err, user) => {
if(err) {
return res.status(400).json({
error: "You are not authorized to update this user"
});
}
user.salt = undefined;
user.encry_password = undefined;
user.createdAt = undefined;
user.updatedAt = undefined;
console.log(user);
return res.json(user);
}
);
};
Front-end output
In the server-side code, you can see that I am returning the res.json. but On the client-side, I am not getting the value that I have returned from the server.
Please, can anyone help me?

You need to add one more then(). when you call response.json() it also returns a promise apply a then call when you return response.json()

Related

an empty object arrives in my backend server when i send from my frontend

An empty object arrives in my backend server when I send from my frontend.
My backend server should work fine as I tested it with postman. When I send the following JSON via postman I get a 200 response.
{"email":"tom#gmail.com","password":"123456"}
I have a problem when I send the object via my frontend-code to my backend. The backend server crashes because it recieves an empty object. Why is that?
When i console.log enteredUsername, it's not empty
console.log(enteredUsername, enteredPassword);
let url = "http://localhost:4000/"
fetch(url, {
method: 'POST',
body: JSON.stringify({
email: enteredUsername,
password: enteredPassword
}),
headers: {
'Content-Type': 'application/json',
},
mode: 'no-cors'
}).then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then((data) => {
let errorMessage = 'Authentication failed!';
// if (data && data.error && data.error.message) {
// errorMessage = data.error.message;
// }
throw new Error(errorMessage);
});
}
})
.then((data) => {
console.log(data);
})
.catch((err) => {
alert(err.message);
});
}
This is the code from my backend server. When i console.log user, it's empty
router.post('/', async (req,res)=>{
console.log(req.body);
const result = await data.addUser(req.body);
res.send(result);
});
this is the method addUser:
async function addUser(user){
const connectionDB = await connection.getConnection();
console.log(user);
user.password = bcrypt.hashSync(user.password,8);
const result = await connectionDB.db('my-website')
.collection('users')
.insertOne(user);
return result;
}
I get this error in my console of my browser:
POST http://localhost:4000/ net::ERR_CONNECTION_RESET
Thank you very much for helping me.

Res.send not a function

I have an endpoint (using express) which requires me to do some fetching first. Once a parse the response and use res.send I get an error res.send is not a function.
I tried searching for this error but all searches show users had res,req in the wrong order. In this case, mine appear to be right.
Why is it res is not scope after a convert my response to JSON?
router.post("/customerID", async (req, res) => {
return fetch({endPoint}, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Flowspace-Auth": {myToken},
},
body: JSON.stringify({
query: `query {
user {
name
organizationId
}
}`,
}),
})
.then((res) => {
res.json().then((data) => {
console.log(data) // This works
res.send({ data: data }); // res.send is not a function... why, is it not scoped correctly?
});
})
.catch((err) => console.log("unable to fetch:", err));
});
Your outer response variable is overwritten by your inner result variable. JS goes from the inner most scope to outer most looking for variable. Since, res is already defined in the then clause, that res is used.
Changing it to resp should work.
router.post("/customerID", async (req, resp) => {
return fetch({endPoint}, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Flowspace-Auth": {myToken},
},
body: JSON.stringify({
query: `query {
user {
name
organizationId
}
}`,
}),
})
.then((res) => {
res.json().then((data) => {
console.log(data) // This works
resp.send({ data: data }); // resp will belong to outer response
});
})
.catch((err) => console.log("unable to fetch:", err));
});
You probably want to send something in the catch part too.
You are calling send method on the response of the fetch api call on which the send method is not available. find the correct code below.
router.post("/customerID", async (req, res) => {
return fetch(
{ endPoint },
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Flowspace-Auth": { myToken },
},
body: JSON.stringify({
query: `query {
user {
name
organizationId
}
}`,
}),
}
)
.then((response) => {
response.json().then((data) => {
console.log(data); // This works
res.send({ data: data });
});
})
.catch((err) => console.log("unable to fetch:", err));
});

Cookie error while trying to authenticate for data scraping

I'm trying to scrape some data from truepush website, but first it needs to be authenticated. So here is what I'm doing:
const loginUrl = 'https://app.truepush.com/api/v1/login'
let loginResult = await axios.get(loginUrl)
.then(({ headers }, err) => {
if (err) console.error(err);
return headers['set-cookie'][0];
})
.then((cookie, err) => {
if (err) console.error(err);
const splitByXsrfCookieName = cookie.split("XSRF-TOKEN=")[1]
return splitByXsrfCookieName.split(';')[0];
}).then(xsrfToken => {
return axios.post(loginUrl, {
headers: {
"Content-Type": "application/json",
"X-XSRF-TOKEN": xsrfToken
}
})
}).then(res => console.log(res))
It throws xrsfToken on second then response and when I try to login in third response with that xsrf token, it shows me this error:
{
"status_code": "XSRF-ERROR",
"status": "ERROR",
"message": "Cross domain requests are not accepting to this endpoint. If you cleared the cookies, please refresh your browser."
}
I'm not sure what wrong I'm doing :(
The main issue is that the call also requires the original cookie to be sent. You need to keep the original cookie your get from set-cookie header and pass it in cookie header in the second call like cookie: originalCookie. Also in your code, there is no body sent in the POST call.
The following code reproduces the login :
const axios = require("axios");
const originalUrl = 'https://app.truepush.com';
const loginUrl = 'https://app.truepush.com/api/v1/login';
const email = "your-email#xxxxxx";
const password = "your-password";
(async () => {
await axios.get(originalUrl)
.then(({ headers }, err) => {
if (err) console.error(err);
const cookie = headers['set-cookie'][0];
return {
cookie: cookie,
xsrfToken: cookie.split("XSRF-TOKEN=")[1].split(";")[0]
};
})
.then((data, err) => {
if (err) console.error(err);
return axios.post(loginUrl, {
"email": email,
"password": password,
"keepMeLoggedIn": "yes"
}, {
headers: {
"X-XSRF-TOKEN": data.xsrfToken,
"cookie": data.cookie
}
})
})
.then(res => console.log(res.data))
})();
Output:
{
status_code: 'SUCCESS',
status: 'SUCCESS',
message: 'Login Successful',
data: {
id: 'xxxxxxxxxxxxxxxxxxx',
name: 'xxxxx',
email: 'xxxxxxx#xxxxxx'
}
}
Note that both cookie and xsrfToken are consumed by the second promise

Why does my api post request (Vue.js client) receive an undefined response from my express server?

My client is Vue.js using a Vuex store. I am using passport.js for authentication on the server side. Login and account registration is working. Checking mongodb shows new data. But express is sending an undefined response to the client. This is my first major javascript project so I'm hoping it's something simple my eyes just can't see yet.
client: api.js
export async function registerUser(user) {
console.log("api to register user");
console.log(user);
const route = `${api}/register`;
return fetch(route, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(user)
})
.then(response => {
console.log(response.json());
return response.json();
})
.then(json => {
console.log(json);
return json;
})
.catch(err => {
console.error(err);
});
}
client: index.js (vuex store where res is undefined)
actions: {
async register(state, user) {
apis.registerUser(user).then(res => {
if (res.success) {
this.dispatch("loadUser");
alert("successfully registered");
}
});
},
async loadUser() {
apis.getUser().then(res => {
this.commit("setUser", res.user);
});
}
}
server: app.js
app.post('/api/v1/register', function(req, res) {
const success = true;
Users=new User({email: req.body.email, username : req.body.username});
console.log(req.body);
User.register(Users, req.body.password, function(err, user) {
if (err) {
console.log('account could not be saved');
success = false;
} else {
console.log('account saved');
}
})
res.send({success: success});
});
fetch error printing to console
The server console.logs in the app.js route indicate the req.body has the right data and user account is saved successfully. No errors occur on res.send but the client gets an undefined response.
After much banging my head against the table and some outside assistance, I found a solution. I had two main issues.
I was not preventing the default on the submit button so the form was refreshing before the request was properly handled.
Mishandling of javascript promises.
Working code below:
api.js
export function registerUser(user) {
console.log("api to register user");
console.log(user);
const route = `${api}/register`;
return fetch(route, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(user)
})
.then(response => {
console.log(response.json());
return response.json();
})
}
index.js (vuex store)
actions: {
register(state, user) {
apis.registerUser(user).then(res => {
if (res.success) {
alert("successfully registered");
}
}).catch(err => {
console.error(err);
});
}
}
app.js code remained the same

ReactJS and Node.JS [JSON.parse: unexpected character at line 1 column 1 of the JSON data]

I'm getting struggle with this code, so I need a third eye on this to find a solution.
I'm developing a ReactJS app with a REST API with Node.JS (Express), and I'm getting this error:
SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"
I'm using Sequelize ORM to work with Models and Database in Node.JS.
I'm also using CORS module for Node.JS.
This implementation works fine.
// Node.js Route for login
const router = require('express').Router();
const User = require('user');
router.post("/login", async (req, res) => {
try {
await User.findOne({
where: {
email: req.body.email,
password: req.body.password,
}
}).then((user) => {
if (!user) {
return res.send({message: "Login error!"});
} else {
const userData = {id: user.id, email: user.email};
res.send({"user": userData});
}
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for login
loginFunction(e, data) {
e.preventDefault();
fetch('http://localhost:4500/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(json => {
this.setState({'user': json['user']});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Login error"})
});
}
On the other hand, this implementation do not work properly and throws the SyntaxError above:
// Node.JS for Posts
const router = require('express').Router();
const Post = require('post');
router.get("/posts", async (req, res) => {
try {
await Post.findAndCountAll()
.then((posts) => {
res.send({"posts": posts});
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for Posts
postsFunction() {
fetch('http://localhost:4500/posts', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(json => {
this.setState({'posts': json.posts.rows});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Posts error."})
});
}
As you can see both implementation have little differences, What am I missing?
PS: When I test the 2nd implementation on Postman, data is retrieving successfully.
try removing headers when using GET method
headers: {
'Content-Type': 'application/json'
}
Try to use res.json instead of res.send in the node js function that cause the error.
I found the issue!
I follow the (#vengleab so) suggestion:
console log response instead of response => response.json()
I'm realize that response returns an object like this:
Response: {
body: ReadableStream
locked: false
<prototype>: object { … }
bodyUsed: false
headers: Headers { }
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:3000/admin/undefined/posts"
}
The URL attribute contain an undefined value, so when I try to console.log the .env variable API_URL that contains the localhost URL used in this line:
fetch('http://localhost:4500/posts', {
That in real function is:
fetch(process.env.API_URL + '/posts', {
The result of the console.log was undefined.
As it is explained in Create React App docs, the environment variables must start with the prefix REACT_APP_.
Finally the line works as:
fetch(process.env.REACT_APP_API_URL + '/posts', {
I found that it was because my front end react url pointed to the same url as my backend server.js running mongodb. Also clearing the cookies on the browser seems to have helped as well.

Categories