Not sure if intended or not since there isn't anything either way in the tests or documentation, but when you reply with a Promise from a server route and that promise is rejected, hapi will return a successful status code and serialize the rejection reason as the body of the response. It looks like resolving OR rejecting any object that is not an instance of Error is treated as a successful response, while resolving OR rejecting any object that IS an instance of Error is treated as an unsuccessful response.
This feels very counter to how Promises are supposed to be used. If this is expected, is there a recommended approach to turning rejected promises into an error status?
Test case?
server.route({
method: 'GET',
path: '/',
handler: (request, reply) => {
reply(new Promise((res, rej) => { throw "up"; })); // returns 200 OK
}
});
server.route({
method: 'GET',
path: '/',
handler: (request, reply) => {
reply(Promise.reject({ err: 'some issue'})); // returns 200 OK
}
});
// idk why you would want to do this...
server.route({
method: 'GET',
path: '/',
handler: (request, reply) => {
reply(Promise.resolve(new Error("something"))); // returns 500 Server Error
}
});
What behaviour do you expect for these?
I'd expect 500 for both, with suitable detail in the log's fine print. Hapi's half way there already.
Also should Hapi handle promise unhandledRejection?
UPD: I think some code can ignore promise rejections on purpose, so it's not always an error. But maybe hapi may help handler writer to catch rejections per request.
const thirdPartyCode = function(callback) {
new Promise( (resolve, reject) => {
console.log('Throwing!');
throw new Error('Nobody catches me!');
} )
.then( callback )
// .catch( reply ) // Oh no, we forgot to add a catch!
return 'Please, use callback.';
};
server.route({
method: 'GET',
path: '/',
handler: function(request, reply) {
return thirdPartyCode( reply ); // Reply never called.
/* Doesn't work.
return new Promise( (resolve, reject) => thirdPartyCode( resolve ) )
.then( reply )
.catch( reply );
*/
}
});
process.on( 'unhandledRejection', () => console.log('Unhandled by hapi! Sorry.') );
yeah we should fix this. i'll write up a test and patch later today.
as for the unhandledRejection handling, if you're careful about passing a promise to reply rather than passing reply as an argument to a method that uses promises, the unhandled rejection is much less likely. that said, having a fallback isn't a terrible idea though i would definitely prefer that it were optional.
unhandledRejection doesn't belong in hapi.
Most helpful comment
Also should Hapi handle promise
unhandledRejection?UPD: I think some code can ignore promise rejections on purpose, so it's not always an error. But maybe hapi may help handler writer to catch rejections per request.