So I'm passing user entered data to the backend, but req.body is coming back undefined and i'm not sure why. I've set up my middleware beforehand, yet I still get undefined. I have also checked the the value being sent by axios and has checked out to be correct.
app.use(Cors());
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}));
app.post('/signup', (req, res) => {
//const { email } = req.body;
console.log(req.body.email);
if(!req.body.email) {
console.log("No email, failed");
return;
}
const data = {
members: [
{
email_address: req.body.email,
status: "subscribed"
}
]
}
const postData = JSON.stringify(data);
const options = {
url: 'https://us4.api.mailchimp.com/3.0/lists/xxxxxx',
method: 'POST',
headers: {
Authorization: 'xxxxxxx'
},
body : postData
}
request(options, (err, response, body) => {
if(err) {
console.log(err);
} else {
if(response.statusCode === 200) {
console.log("Success!");
}else {
console.log("Error Accessing")
res.send("Error");
}
}
});
});
Here is my axios post method:
handleSubmit = e => {
e.preventDefault();
const { email } = this.state;
axios
.post('http://localhost:5000/signup', email)
.then(() => console.log("Email Added"))
.catch(err => {
console.log(err);
})
};
You have confirmed that what is being POSTed by axios (this.state.email) is not undefined?
The fact that the req body is coming back undefined points to either the data being entered incorrectly or the request for that data being invalid.
What does the entire req.body look like?
My problem was that I was that I was not passing email as an object, hence the object was coming back empty.
Related
I am trying to set up an edit feature to edit a post. Right now I am trying to update a specific post by ID and then I'll make it dynamic.
I can get axios to send the PUT request but I don't receive any indication that it is received on the router. Also the ID I have set it showing up correctly in the URL.
I'm not sure how to send the data over to the router so it can find the ID.
Edit component
function handleSubmit(event){
event.preventDefault()
axios ( {
url: `/api/${props.data[0]._id}`,
method: 'PUT',
headers: { "Content-Type": "multipart/form-data" },
id: props.data[0]._id
})
.then(() => {
console.log(`data has been sent to the server from axios: ${props.data[0]._id}`)
})
.catch(() => {
console.log('Data could not be sent from axios')
})
}
Router
router.put('/:id', async (req, res) => {
try {
const updatedGratitude = await PostGratitude.findByIdAndUpdate(req.params.id)
res.status(200).json(updatedGratitude)
} catch (err){
next(err)
}
})
if you are editing a post then you should send the data in the request as well
like a title: "" and description: "" or something and in the in the router, you could write something like this :
function handleSubmit(event) {
event.preventDefault()
axios({
url: `/api/${props.data[0]._id}`,
method: 'PUT',
headers: { "Content-Type": "application/json" },
data: {
title: '',
description: ''
}
})
.then((response) => {
console.log(response)
})
.catch((err) => {
console.log(err)
})
}
you need to pass the arguments as to what to update as well, here is an example of a code that I wrote
router.put('/updatentry/:id',fetchuser, async (req, res) => {
var success = false
try {
const { title, description } = req.body
let newentry = { title: title , description: description
}
let old_entry = await Journal.findById(req.params.id);
if (!old_entry) {
return res.status(404).send({ success, error: 'Not Found'})
}
const update_entry = await Journal.findByIdAndUpdate(req.params.id, { $set: newentry }, { new: true })
return res.send(res: update_entry)
} catch (error) {
return res.status(500).send(error: 'Internal Server Error')
}
})
This is because you forgot the update body on method. Try this:
PostGratitude.findByIdAndUpdate(req.params.id, req.body)
instead of :
await PostGratitude.findByIdAndUpdate(req.params.id)
Because mongoose can not know what to update :D
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.
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
I'm having a problem using Axios with my backend. It's probably a very simple fix as I'm new to this.
Postman: The correct response is received for both valid and invalid credentials.
Axios: The correct response is received for valid crendentials, but the axios method's catch block is run when invalid credentials are entered.
authController.js:
exports.login = (req, res, next) => {
const email = req.body.email;
const pass = req.body.password;
let loadedUser;
User.findOne({ where: { email: email } })
.then(user => {
if(!user) {
const error = new Error('Incorrect username or password');
error.statusCode = 401;
throw error;
} else {
loadedUser = user;
return bcrypt.compare(pass, user.password);
}
})
.then(isEqual => {
if(!isEqual) {
const error = new Error('Incorrect username or password');
error.statusCode = 401;
throw error;
} else {
const token = jwt.sign(
{
email: loadedUser.email,
userId: loadedUser.id
},
process.env.JWT_SECRET,
{ expiresIn: '1hr' }
);
res.status(200).json({ token: token, userId: loadedUser.id });
}
})
.catch(err => {
if (!err.statusCode)
err.statusCode = 500;
next(err);
});
};
The error handler in app.js. It seems to log the error correctly when incorrect credentials are entered, even with axios:
app.use((error, req, res, next) => {
const status = error.statusCode || 500;
const message = error.message;
const data = error.data || 'No Data';
console.log(status, message, data);
res.status(status).json({message: message, data: data});
});
But then the axios catch block runs, so instead of receiving the json message, I get the following error
login(email, password) {
const headers = {
'Content-Type': 'application/json'
};
const data = JSON.stringify({
email: email,
password: password
});
axios.post('http://127.0.0.1:8080/auth/login', data, { headers })
.then(res => console.log(res))
.catch(err => console.log(err));
}
The error in the console for invalid credentials:
Clicking the link highlighted opens a new page stating: "Cannot GET /auth/login", but I'm obviously making a post request, & I've added post to the form (just in case)
Any ideas what I could be missing?
Thanks
Actually your code works fine but Axios will reject the promise of the call if you have the status 401. If you have a status between 200 to 300 it will resolve the promise.
There two ways to deal with this.
Check status in the catch block.
axios.post('http://127.0.0.1:8080/auth/login', data, {
headers
})
.then(res => console.log(res))
.catch(err => {
if (err.response.status === 401) {
//Auth failed
//Call reentry function
return;
}
return console.log(err)
});
or change the validateStatus option;
axios.post('http://127.0.0.1:8080/auth/login', data, {
headers,
validateStatus: function (status) {
return status >= 200 && status < 300 || (status === 401);
},
})
.then(res => console.log(res))
.catch(err => return console.log(err));
I am running a react app with nodejs acting as an api to connect to my database.
For my log in I am sending data to the server, and it is returning a pass or fail.
However I am not sure how to extract this json object.
I have looked at the request and response, and as I have manipulated the json object the response content-length has been changing so I believe it must be there somewhere.
SERVER CODE:
app.post('/api/checkLogin', async (req,res) => {
console.log(req.body);
const {username, password} = req.body;
try{
let state = await DB.checkPassword(username, password);
console.log(state);
if(!state){
res.status(401).json({
error: 'Incorrect username or password',
yay: 'idk work?'
});
}
else if(state){
res.status(200).json({
message: 'we in boys'
});
} else {
res.status(6969).json({
err: 'idk mane'
});
}
} catch(e) {
console.log(e);
}
})
CLIENT CODE:
onSubmit = (event) => {
event.preventDefault();
fetch('/api/checkLogin', {
method:'POST',
body: JSON.stringify({username: this.state.username, password: md5(this.state.password)}),
headers: {
'Content-Type':'application/json'
}
}).then(res => {
if(res.status ===200) {
this.props.loggedIn();
} else if(res.status ===401){
console.log(res.status);
alert('wrong username or password');
}else{
const error = new Error(res.error);
throw error;
}
}).catch(err => {
console.log(err);
alert(err);
});
}
What I was sort of expecting as a way to extract the data would be.
On the server:
res.status(200).json({ message : 'mssg'});
On the client:
console.log(res.status.message) // 'mssg'
Thanks Jin and this post I found for the help Fetch API get raw value from Response
I have found that both
res.status(xxx).json({ msg: 'mssg'}) and res.status(xxx).send({msg: 'mssg'}) work.
The json, or sent message can then be interpreted on the client side with a nested promise. This is done with...
fetch('xxx',headers n stuff).then(res => {
res.json().then((data) => {console.log(data.message)});
//'mssg'
res.text().then((data) => { let data1 = JSON.parse(data); console.log(data1.message);});
//'mssg'
});
According to my experience, using res.status(200).send({message: 'mssg'}) is better.
And you can get data after calling api by using res.data.
Then you can get result as below:
{
message: 'mssg'
}
Here is something that may help.
onSubmit = (event) => {
event.preventDefault();
const userData = {
username: this.state.username, // I like to store in object before passing in
password: md5(this.state.password)
}
fetch('/api/checkLogin', {
method:'POST',
body: JSON.stringify(userData), //stringify object
headers: {
'Content-Type':'application/json'
}
}).then(res => res.json()) // convert response
.then(responseData => {
let status = responseData.whatObjectWasPassedFromBackEnd;
status === 200 ? do something on pass: do something on fail
})
.catch(err => {
console.log(err);
alert(err);
});
}