У меня есть приложение Node.js, которое использует экспресс, мангуст и паспорт. На этом этапе у меня есть только аутентификация (Google, Facebook и локальная), и все это работает хорошо. Я пытаюсь обработать ошибки всесторонним способом, и борюсь с кодами состояния HTTP. Моя проблема в том, что я не могу полностью контролировать коды состояния HTTP, которые отправляет мое приложение.
Это код в моей локальной стратегии Passport. Как видите, я пытаюсь выбросить две ошибки с разными кодами состояния (чтобы я мог легко их дифференцировать в моих тестовых примерах).
passport.use(
new LocalStrategy(
{ usernameField: 'email' },
async (email, password, done) => {
try {
const user = await User.findOne({ email: email });
if (!user || !user.validPassword(password))
throw new UserError(
'Wrong email or password.',
'/login',
302
);
else if (!user.verified)
throw new UserError(
"This account hasn't been verified. Check your emails.",
'/login',
304
);
else return done(null, user);
} catch (e) {
return done(e);
}
}
)
);
Пользовательский класс ошибок определяется следующим образом:
class UserError extends Error {
constructor(msg, redirect, status) {
super(msg);
this.name = this.constructor.name;
this.msg = msg || 'UserError: Auth + User validation.';
this.redirect = redirect || '/';
this.status = status || 302;
}
}
И обрабатывается этим промежуточным ПО:
const errorHandler = (err, req, res, next) => {
if (err.name == 'UserError') {
req.flash('error', err.msg);
res.redirect(err.status, err.redirect);
// res.redirect(302, err.redirect);
} else if (err.name == 'ValidationError') {
if (err.errors.password) {
req.flash(
'error',
'Server error: Password must be at least 6 characters.'
);
res.redirect('/');
}
if (err.errors.email) {
req.flash(
'error',
'Server error: ' +
err.errors.email.value +
' is not a valid email.'
);
res.redirect('/');
}
// } else if (err.name == 'MongoError') {
// res.send(err);
// } else if (err.name == 'JsonWebTokenError') {
// res.send(err);
} else {
console.log(err);
res.send(err);
}
};
Как видите, я пытаюсь сгенерировать ошибки с помощью пользовательского кода состояния HTTP (по умолчанию 302, если для вызова UserError () код состояния не указан).
А вот мои тесты:
it('Wrong credentials -> 304, with redirection to /login', (done) => {
request
.post(`${baseUrl}/login/email`)
.type('form')
.send({
email: users[0].email,
password: users[1].password
})
.end((err, res) => {
expect(res.statusCode).toBe(304);
expect(res.headers.location).toBe('/login');
done();
});
});
it('Unverified user -> 304, with redirection to /login', (done) => {
agent
.post(`${baseUrl}/login/email`)
.type('form')
.send({
email: users[1].email,
password: users[1].password
})
.end((err, res) => {
expect(res.statusCode).toBe(304);
expect(res.headers.location).toBe('/login');
done();
});
});
Неожиданное поведение заключается в том, что ожидаемые вызовы в моих тестовых пакетах говорят мне, что они получают очень неожиданные коды состояния HTTP:
- Если я попытаюсь выдать ошибку со статусом 304 => Я получу 304. Все счастливы.
- Кидаю со статусом 300 => Я получаю 300. Пока все хорошо.
- Попробуйте бросить со статусом 301, 302 или 303 => Я получу 200.
- Попробуйте бросить со статусом 305, 307 или 307 => Я получаю 404.
Так что определенно есть что-то, что я не правильно понимаю, но я не знаю, это коды состояния HTTP, правильный способ res.redirect () или способ работы Passport ... Любое задним числом будет приветствоваться что происходит за кулисами!