我有一个使用Express,猫鼬和Passport的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状态代码生成错误(如果没有为UserError()调用提供状态代码,则默认为302)。
这是我的测试用例:
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();
});
});
意外的行为是我的测试套件中的Expect调用告诉我它们收到了非常意外的HTTP状态代码:
所以肯定有一些我不正确理解的东西,但是我不知道这是HTTP状态代码,res.redirect()的正确方法还是Passport的工作方式……在此欢迎任何后见之明。幕后发生了什么!