简体   繁体   中英

How to use res.render and res.redirect in the same function

I am developing a widget for user login. Basically, when they input valid account details I want it to render the same page (using handlebars) and state something like "Account successfully validated" and then 3 seconds later redirect the user.

This is the current code I have

router.post('/auth', (req, res, next) => {
    let username = req.body.username;
    let password = req.body.password;

    if (username && password) {
        connection.query('SELECT * FROM accounts WHERE username = ? AND password = ?', [username, password], (error, results, fields) => {
            if (results.length > 0) {
                req.session.loggedin = true;
                req.session.username = username;

                res.render('login.hbs', {
                    access: new hbs.SafeString('<p>Account successfully authenticated!</p>') // Display custom message
                });

                setTimeout(() => {
                    res.redirect('/admin'); // Redirect user
                }, 3000);

            } else {
                res.render('login.hbs', {
                    access: new hbs.SafeString('<p style="font-size: 1.2rem; margin-top: 2rem; color: red; font-weight:700;">Incorrect Username and/or Password!</p>')
                });
            }           
        });
    } else {
        res.render('login.hbs', {
            access: 'Please enter Username and Password'
        });
    }
});

However, whenever I try to do this I get the 'Cannot set headers after they have been sent to the client' Can someone please educate me on what the header system is and how I can fix this to get the desired result?

Thank you!

res.redirect() works by setting a Location HTTP header. Those headers must be sent before any content is delivered to the client via the response body.

As an alternative to handling this delayed redirect client-side, you could use the non-standardised* Refresh header that allows to specify a delay in seconds before the redirect happens. Just add

res.set({'Refresh': '5; url=/admin'});

before you call res.render() .

* It was introduced by Netscape way back and since adopted by all major browsers, so despite never making it into the official HTTP standard, it's pretty safe to use it.

And as a "bonus", if you were to solve it client-side, you would add

 <meta http-equiv="refresh" content="5; url=/admin"/>

to the header of your returned HTML markup, which does exactly the same.

What's happening is. After you send a response, a particular request has been closed. The browser is no longer listening or connected to the same request. So after sending a response, res.redirect() is throwing an error as the request is closed.

What you can do is you can pass some flag or something similar, and handle redirection on the client-side.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM