Reputation: 9417
I started using v17
of Hapi.js
and I am running into issues when using the pre-handler.
I want to save a user into a database, but first I use the pre-handler to check if a user already exists. If the user exists, I want to throw an error. The structure of my route is as so...
module.exports = {
method: "POST",
path: "/users",
config: {
auth: false,
pre: [{ method: verify_unique_user}],
handler: create_user.create
}
}
The content of verify_unique_user
is...
async function verify_unique_user(req, h) {
await User.findOne({
$or: [{email: req.payload.email}, {username: req.payload.username}]
},
(err, user) => {
if (user) {
// Check if username exists.
if (user.username === req.payload.username) {
throw Boom.badRequest("Username taken!");
}
// Check if email exists.
if (user.email === req.payload.email) {
throw Boom.badRequest("Email taken!");
}
}
});
return req;
}
Let's assume the user already exists in the database. Then an error will be thrown from either of the if
statements. When this happens, I get the following error...
events.js:167
throw er; // Unhandled 'error' event ^
Error: Username taken! at User.findOne (/Users/ericbolboa/Desktop/Warble/server/src/users/util/user_function.js:16:16)
This crashed my server. This is not what I want. If I throw an error in my handler function, the response looks like this...
{
"statusCode": 400,
"error": "Bad Request",
"message": "error"
}
But whenever I throw an error in the pre-handler, my server crashes. How can I throw errors properly?
Upvotes: 1
Views: 2674
Reputation: 3838
Take a look at the toolkit(h) and options.response.failAction
of route.
A route can set response.failAction
in options. There, you can format error messages, and send response, however you please. That includes errors thrown from pre handlers.
Edit: Every pre-handler can have it's own 'failAction' handler. You must do a response(...).takeover()
if you want to halt the chain.
Upvotes: 1
Reputation: 1158
Not sure if this is the source of the issue but you can simplify the async/await instead of using the callback
async function verify_unique_user(req, h) {
const user = await User.findOne({
$or: [{email: req.payload.email}, {username: req.payload.username}]
});
// Check if username exists.
if (user.username === req.payload.username) {
throw Boom.badRequest("Username taken!");
}
// Check if email exists.
if (user.email === req.payload.email) {
throw Boom.badRequest("Email taken!");
}
return req;
}
Upvotes: 3