Home > Back-end >  Cannot set headers after they are sent to the client NodeJS Redirect
Cannot set headers after they are sent to the client NodeJS Redirect

Time:06-26

I have some IF/Else stataments, in IF statament I could make an redirect, but in else statament I couldn't. Code that I use:

app.use(express.static(__dirname   '/public'));
router.get('/',function(req,res) {
    res.sendFile(path.join(__dirname   '/public/html/index.html'));
    var email = req.query.email;

    conn.query("SELECT * FROM users WHERE email = ?", [email], function(err, result){
        if (err) throw err;
        var resultLength = result.length;
        if (email != null && resultLength == 0) {
            conn.query('INSERT INTO users (email) VALUES (?)', [email], function(err, result) {
                if (err) throw err;
                console.log('1 record inserted')
                res.write('<p>You are now subscribed to our newsletter!</p>');
            })
            res.redirect('/succes')
        }else{
            console.log("You are already subscribed to our newsletter!")
            res.redirect('/error')
        }


    })


});

CodePudding user response:

You can send ONE and only one response to a given request. When you do:

res.sendFile(...)

that sends a response to the incoming request. Attempting to send ANY other request will cause the error about "cannot send headers after they are already sent".

Yet, in your code, you then try to do both res.write(...) and res.redirect(...). You simply can't do that. You get to send one and only one response to a given incoming request. You already sent one with res.sendFile(...).

Then, even further, you can't do a res.write(...), then followed by res.redirect(...). Doing a res.write(...) means that the http library has to send the headers so that it can now start sending the body. So, this forces the headers to get sent. But, now when you do a res.redirect(...), you're telling the Express library that you want to set a 302 status code and you want to set the Location header. Hmmm, but the status code has already been sent and the headers have already been sent, forced out by the res.write(...). So, at this point, res.redirect(...) cannot do its job.

It's unclear what this code is supposed to do. You're either serving index.html or you're doing something else that redirects to a different URL. The same route can't do both of those operations. For a route like this, you either send an HTML response OR you redirect to another URL. Pick one.


Here's one possible solution that contains only res.redirect():

router.get('/', function(req, res) {
    const email = req.query.email;
    if (!email) {
        console.log("req.query.email not present");
        res.redirect('/error')
        return;
    }

    conn.query("SELECT * FROM users WHERE email = ?", [email], function(err, result) {
        if (err) {
            console.log(err);
            res.redirect('/error')
            return;
        }
        const resultLength = result.length;
        if (resultLength == 0) {
            conn.query('INSERT INTO users (email) VALUES (?)', [email], function(err, result) {
                if (err) {
                    console.log(err);
                    res.redirect('/error')
                    return;
                }
                console.log('1 record inserted')
                res.redirect('/succes');
                return;
            })
        } else {
            console.log("You are already subscribed to our newsletter!")
            res.redirect('/error')
            return;
        }
    });
});
  • Related