Представьте себе веб-приложение с маршрутами, которым необходимо проверить, разрешен ли пользователю доступ к данному ресурсу, прежде чем продолжить. Проверка подлинности основана на вызове базы данных.
В каждом маршруте у меня может быть:
authorizeOwnership(req, res)
.then(function() {
// do stuff
res.send(200, "Yay");
});
Я хочу, чтобы функция authorizeOwnership()
обрабатывала ответы 403 (отказано в доступе) и 500 (например, ошибка запроса к базе данных), чтобы каждому маршруту не нужно было делать это явно.
У меня есть функция, которая может запросить базу данных, чтобы проверить право собственности.
function confirmOwnership(resourceId, userId) {
// SequelizeJS... returns a bluebird promise
return Resource.find({
where: {id: resourceId, userId: userId}
})
.then(function(resource) {
if(!resource) {
return null; // no match for this resource id + user id
} else {
return resource;
}
});
}
Затем это используется в authorizeOwnership
:
function authorizeOwnership(req, res) {
var rid = parseInt(req.params.rid, 10),
userId = parseInt(req.authInfo.userid, 10);
return new Promise(function(resolve, reject) {
confirmOwnership(rid, userId)
.then(function(resource) {
if(resource === null) {
res.send(403, "Forbidden");
// Note: we don't resolve; outer handler will not be called
} else {
resolve(resource);
}
})
.catch(function(err) {
console.log(err);
res.send(500, "Server error");
// Note: we don't resolve; outer handler will not be called
});
});
}
В этом сценарии я намеренно не вызываю reject()
или resolve()
в некоторых путях кода. Если я это сделаю, то моя «внешняя» логика маршрута (код, вызывающий authorizeOwnership()
) усложнится, потому что она должна обрабатывать ошибки (либо с проверкой .catch()
, либо с проверкой null
в .then()
).
Но две вещи меня немного нервируют:
Можно ли, чтобы обещание, возвращаемое
authorizeOwnership()
, никогда не разрешалось в сценариях ошибок? Это вызовет задержку или утечку памяти?Логично ли разрешить
confirmOwnership()
с нулевым значением, чтобы сказать «подходящий ресурс не найден», а затем рассматривать это как ошибку вauthorizeOwnership()
? Моя первая попытка отклонила обещание вconfirmOwnership()
, когда не было подходящего ресурса, но это усложнило ситуацию, потому что трудно отличить это (случай 403) от фактической ошибки (случай 500).