Reputation: 41
I,m learning MongoDB and mongoose and now I have a problem in defining a 404 status for my route handler. Here is the code:
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(500).send()
}
})
Now if I give it an id that doesn't exist, it doesn't give me 404 Not Found status. it only executes the catch block which is not what I want. I would appreciate it if you tell me where I made mistake or tell me a way to get error handling for that. Thanks
Upvotes: 3
Views: 2250
Reputation: 1
You can solve this issue by validating your IDs before entering the try-catch block of your code using mongoose
built-in function isValidObjectId()
You can modify your code to be as follows:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id
try {
// ADD THIS CHECK
if (!mongoose.isValidObjectID(_id){ // This checks allows us to not go into catch block and return appropriate response
return res.status(404).send()
}
const user = await User.findById(_id)
if (!user) {
return res.status(404).send()
}
res.send(user)
} catch (error) {
res.status(500).send()
}
});
I took reference from these for the same:
Upvotes: 0
Reputation: 5411
As you can see in the log
CastError: Cast to ObjectId failed for value "6082d50a2c89db3164" at path "_id" for model "User"
It means : the value you provide to findById
function ("6082d50a2c89db3164") is not a valid ObjectId.Then the catch block is executed.
1. Validate the parameter before query in database
I understand that you're trying to provide some id that doesn't exist in the database to test. But IMHO, there a difference between 2 cases :
app.get('/users/:id', async (req, res) => {
const _id = req.params.id;
// validate params
if(!isValidateObjectId(_id)) { // the function we need to write
res.status(200).send("Invalid params"); // you can define your status and message
return;
}
// good params, get user from database
try {
const user = await User.findById(_id)
if (!user) {
return res.status(404).send()
}
res.send(user)
} catch (error) {
res.status(500).send()
}
})
2. Use findOne() method instead of findById
If you want a simpler solution, don't use findById because the function expects a valid ObjectId. We can use findOne() method :
app.get('/users/:id', async (req, res) => {
const _id = req.params.id
try {
const user = await User.findOne({_id : _id})
if (!user) {
return res.status(404).send()
}
res.send(user)
} catch (error) {
res.status(500).send()
}
})
(IMHO, the first solution is better though..)
Some helpful link :
Upvotes: 1