具有不同状态代码的res.redirect()的异常行为

时间:2018-11-01 16:10:06

标签: node.js express passport.js http-status-codes

我有一个使用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状态代码:

  • 如果我尝试以状态304抛出错误=>我得到304。每个人都很高兴。
  • 投掷状态为300 =>我得到300。到目前为止,一切都很好。
  • 尝试以状态301、302或303投掷=>我得到200。
  • 尝试以状态305、307或307投掷=>我得到404。

所以肯定有一些我不正确理解的东西,但是我不知道这是HTTP状态代码,res.redirect()的正确方法还是Passport的工作方式……在此欢迎任何后见之明。幕后发生了什么!

0 个答案:

没有答案