How can I get custom HTTP error messages? - javascript

Here im making a request to from the frontend to backend:
await axios.post("http://localhost:5000/users/signin", data) // <- sending wrong data
.then()
.catch((err) => console.log(err.message)); // <-- here the response is 404
Here i make the request to the mongodb:
const signin = async (req, res) => {
const { email } = req.body;
try {
const existingUser = await User.findOne({ email });
if (!existingUser) return res.status(404).json({ message: "User not found." });
};
router.route("/signin").post(signin)
Bacically i want when the user sends wrong data i want the err.message i get to be "User not found." but it is Request failed with status code 404.
Why?

Because err.message is not where the JSON data is stored; Instead use err.response.data (err.response is the actual response from the web server, err is what is raised by the axios.post() failing)

Related

Unable to Pass Data to Backend from Input

I have an API which will send an email to a user based off the input. This is the on lick submit. I can confirm the data is being console.log for the state.
const inviteUser = async () => {
userRequest.get(`companyprofile/companyUser/invite/${companyuser._id}`, teamMemberEmail);
console.log('invite sent to', (teamMemberEmail))
}
With this api, i send the body to the API and then email based off the text, however when i log the field it does not appear at all and only shows as {}
router.get("/companyUser/invite/:id", async (req, res) => {
// must update to company
var stringLength = 25;
const companyUser = await CompanyProfile.findById(req.params.id)
const companyUserToken = await companyUser.inviteToken
const companyAccessTokenStripped = await companyUserToken.substring(0, stringLength);
//encrypt the accesstoken to invite users
const url = `http://localhost:5000/api/auth/inviteToJoinTeam/${companyUserToken}/${req.body.email}`;
// const url = `http://localhost:5000/api/companyprofile/companyUser/inviteToJoinTeam/${companyUserToken}`;
console.log(req.body)
const mailOptions = {
from: 'company#gmail.com',
to: req.body.email,
subject: `You have been invited to join ${companyUser.CompanyTitle}`,
html: `${companyUser.companyTitle} has invited you to join their team ${url}`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
try {
// const savedCompany = await newCompany.save();
res.status(201).json(companyUserToken);
} catch (err) {
res.status(500).json(err);
}
});
Can anyone see why i cannot pass this data and email the user? Appears to be an error with how it's passed but i can confirm that the endpoint works in postman if i just plug an email body in
You are trying to send an email whenever the GET route is called. However, the data won't be sent inside as "req.body" as a GET request doesn't have a body.
If you are using GET method then the data is sent as query parameters.
router.get("/companyUser/invite/:email", async (req, res, next) => {
console.log(req.params.email);
};
You can also either use a POST or PUT request in order to access the URL body
router.post("/companyUser/invite", async (req, res, next) => {
console.log(req.body.email);
};

Express app error: [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

const router = require("express").Router();
const mongoose = require("mongoose");
const User = require("../models/Users");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
// Route 1: create new user at /api/createuser
router.post("/createuser", async (req, res) => {
try {
console.log(req.body);
const salt = await bcrypt.genSaltSync(10);
const hash = await bcrypt.hashSync(req.body.password, salt);
password = hash;
const user = new User({
name: req.body.name,
email: req.body.email,
password: password,
});
user
.save()
.then(() => {
res.json({ message: "User created successfully" });
})
.catch((err) => {
res.json({ message: "Error: " + err });
});
console.log(password);
} catch (err) {
res.json({ message: err });
}
});
// Route 2: Login user at /api/login
router.post("/login", async (req, res) => {
try {
console.log("login endpoint triggered");
const user = await User.findOne({ email: req.body.email });
if (!user) {
res.json({ message: "User does not exist" });
}
const passwordIsValid = await bcrypt.compare(
req.body.password,
user.password
);
if (!passwordIsValid) {
res.json({ message: "Invalid password" });
} else {
const data = {
id: user._id,
};
const token = await jwt.sign(data, process.env.SECRET);
res.json(token);
}
} catch (error) {
res.json({ message: error });
}
});
module.exports = router;
Whenever I am testing the login endpoint, my app crashes if i try to put incorrect password or unregistered email.
It says Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I have only sent one response to the client even then it is showing this error.
In the terminal, it is showing error at catch block of login endpoint.
Can anyone look into it and tell me why am i getting this error.
Make sure that when the response is an error, the rest of the middleware is not executed any more. For example, put a return before the res.json statement:
if (!user) {
return res.json({ message: "User does not exist" });
}
Otherwise, the "Invalid password" json might get issued after this one, but two res.jsons in one response lead to the observed error.

Troubles with nodejs GET endpoint

I have the following endpoint:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id;
try {
const user = await User.findById(_id);
if(!user) {
res.status(404).send();
}
res.send(user);
} catch (e) {
res.status(500).send(e);
}});
When I make the request with a valid user ID, the server sends back the user, no problem with that.
The problem is when I try to find a user with a ID which doesnt exist in the database. The server should response with a 404 Error but instead it sends back a Error 500 and I dont understand why!
Could anyone help me please?
Thank you in advance!
One nice way to handle the errors is to create an express error middleware, this allows you to put all of your error handling in one place so that you dont have to write it more than once.
With express when you use async routes handlers if a promise rejects the error will automatically be passed to the next error middleware.
// First register all of your routes
app.get('/user/:id', async (req, res) => {
const user = await User.findById(req.params.id);
if(!user) return res.status(404).send();
res.send(user);
})
// Then register you error middleware
app.use((err, req, res, next) => {
console.error(err.message)
// if mongoose validation error respond with 400
if(err.message.toLowerCase().includes('validation failed'))
return res.sendStatus(400)
// if moongoose failed because of duplicate key
if(err.message.toLowerCase().includes('duplicate key'))
return res.sendStatus(409)
// if mongoose failed to cast object id
if(err.message.toLowerCase().includes('objectid failed'))
return res.sendStatus(404)
res.sendStatus(500)
})
Thank you for your answers.
I have solved it adding the following to the user model schema:
_id: {type: String}
And adding a return before sending the 404 error:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id;
try {
const user = await User.findById(_id);
if (!user) {
return res.status(404).send();
}
res.send(user);
} catch (error) {
res.status(400).send(error);
}});

Handling error sent back by express in postman

I am working with postman where i am sending my post data to api to insert data in mongodb.My issue is that i am not able to handle the error message properly. Here is my code for it
exports.addUser = (req, res, next) => {
const db = getdb();
// console.log(db)
// console.log(db)
db.collection12("user").insertOne({
name: req.body.name,
password:req.body.password
}).then((result) => {
res.send(result)
}).catch((err) => {
res.status(404).send('Error in adding')
});
};
so i knowingly made and error and wrote "collection12" so that i get and error but then in my catch method i am returning
("Error in addding")
so why then in postman i am not able to see this instead of that i am seeing a hude error meassge that says
See error here
I guess than same would be the issue in my react side where instead of getting my own error meassge i would get this huge message
You actually don't enter the catch block because it cannot even execute the db call. If you want a 404 error to be dispatched in this situation you need to add a try/catch statement like this:
exports.addUser = (req, res, next) => {
const db = getdb();
// console.log(db)
// console.log(db)
try {
db.collection12("user").insertOne({
name: req.body.name,
password:req.body.password
}).then((result) => {
res.send(result)
}).catch((err) => {
res.status(404).send('Error in adding')
});
} catch {
res.status(404).send('Error in adding')
}
};

Unable to Set Cookie in Node JS - React

I am using Node JS on serverside and React on client side. On successful auth when i try to use res.cookie and set a cookie. On client side however the Cookie only shows up in Network tab and does not get set in application tab. I am using axios for making the request and have even set the credentials header to include since I am using cors. Here is my code below
router.post("/", (req, res) => {
console.log(req);
const email = req.body.email;
const password = req.body.password;
loginService.login(email, password, (userPublicData, token, err) => {
if (err) {
res.status(401);
res.send({ user: null, error: err });
} else {
res.status(200);
res.cookie("jwt", token);
res.send({ user: userPublicData, error: err });
}
});
});
Here is my client side function
async function authenticateUser() {
console.log(values);
axios.defaults.headers.common["credentials"] = "include";
axios
.post("http://localhost:8080/api/login", values)
.then(response => response.data)
.then(dataJson => {
sessionStorage.setItem("userData", dataJson);
props.history.push("/admin");
})
.catch(err => {
console.error("Auth error", err);
});
}
The cookie appears in network tab but doesnot get set in the application cookies. Some help would be much appreciated

Categories