1

Im a beginner at using Node js. Ive developed a website with server fetching using PHP and was trying out something new. So can anyone tell me what Im doing wring here?

var mysql = require('mysql');
var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var path = require('path');

var connection = mysql.createConnection({
    host    : 'localhost',
    user    : 'username',
    password: 'password',
    database: 'nodelogin'
});

var app = express();
app.use(session({
    secret: 'secret',
    resave: true,
    saveUninitialized: true
}));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.get('/', (request, response) => {
    response.sendFile(path.join(__dirname + '/login.html'));
});

app.post('/auth', (request, response) => {
    var username = request.body.username;
    var password = request.body.password;
    if (username && password) {
        connection.query('SELECT * FROM accounts WHERE username = ? AND password = ?', [username, password], (error, results, fields) => {
            if (results.length > 0) {
                request.session.loggedin = true;
                request.session.username = username;
                response.redirect('/home'); // This works
            } else {
                request.session.loggedin = false;
                response.send('<script>alert("Incorrect Username and/or Password!")</script>');
                response.redirect('/home'); // This doesnt work
            }
            response.end();
        });
    } else {
        response.send('Please enter Username and Password!');
        response.end();
    }
});

app.get('/home', (request, response) => {
    if (request.session.loggedin) {
        response.send('Welcome back, ' + request.session.username + '!');
    } else {
        response.send('Please login to view this page!');
    }
    response.end();
});

app.listen(3000);

Ive put up my whole app.js but after authorizing the users login, im trying to redirect to the "/home" which works in the if case but not in the else. This is after the query in the code. The error Im getting is the following, and I really cant make heads or tails of it:

C:\xampp\htdocs\students\node_modules\mysql\lib\protocol\Parser.js:437
      throw err; // Rethrow non-MySQL errors
      ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
←[90m    at ServerResponse.setHeader (_http_outgoing.js:485:11)←[39m
    at ServerResponse.header (C:\xampp\htdocs\students\node_modules\←[4mexpress←[24m\lib\response.js:771:10)
    at ServerResponse.location (C:\xampp\htdocs\students\node_modules\←[4mexpress←[24m\lib\response.js:888:15)
    at ServerResponse.redirect (C:\xampp\htdocs\students\node_modules\←[4mexpress←[24m\lib\response.js:926:18)
    at Query.<anonymous> (C:\xampp\htdocs\students\app.js:39:26)
    at Query.<anonymous> (C:\xampp\htdocs\students\node_modules\←[4mmysql←[24m\lib\Connection.js:526:10)
    at Query._callback (C:\xampp\htdocs\students\node_modules\←[4mmysql←[24m\lib\Connection.js:488:16)
    at Query.Sequence.end (C:\xampp\htdocs\students\node_modules\←[4mmysql←[24m\lib\protocol\sequences\Sequence.js:83:24)
    at Query._handleFinalResultPacket (C:\xampp\htdocs\students\node_modules\←[4mmysql←[24m\lib\protocol\sequences\Query.js:149:8)
    at Query.EofPacket (C:\xampp\htdocs\students\node_modules\←[4mmysql←[24m\lib\protocol\sequences\Query.js:133:8) {
  code: ←[32m'ERR_HTTP_HEADERS_SENT'←[39m
}
[nodemon] app crashed - waiting for file changes before starting...
  • You can't redirect after the `send` function – Mickael B. Jan 28 '20 at 10:46
  • It simply says you cannot redirect after a send. You would have faced this same problem with PHP with the infamous "Headers already sent" error. The cause is that HTTP redirect in any language is implemented as a header. Once you've sent data you cannot go back and change the header – slebetman Jan 28 '20 at 10:49
  • So how do I display that the username/password was incorrect and redirect together? –  Jan 28 '20 at 10:54
  • You can't use redirect after res.send(). You may add it to req to send it to home – Mustafa Kunwa Jan 28 '20 at 10:54
  • Look at session flash, it's a good behaviour for what you need. – BENARD Patrick Jan 28 '20 at 11:01
  • What is there on the client side? You need to send the script and the redirect in one response and then let the client handle it. The client should be able to understand that its a script and a redirect both. That's the way I use to handle this issue. – Pronoy999 Jan 28 '20 at 12:51

2 Answers2

2

Here, you attempt to use res.redirect after using res.send to send an HTML string in a response. res.send comes from the Express framework and takes in data as a parameter. res.send then will then check the structure of the parameter and set the corresponding header as well as an ETag attribute in the header. It essentially implements res.write, res.setHeaders and then finally res.end, which comes from the Nodejs core and results in a "closing" of the response, effectively rendering many of the response object methods unusable since they require the response object to be "open". res.redirect is one such method that cannot be used after res.end is called (i.e. the response has been closed/is "over"). In other frameworks, a thread is dedicated to an http response and stops when the response itself has been closed. This isn't the case in Nodejs.

I would consider sending a response to the client via res.send that the client can look for as a signal to do a redirect, perhaps using something like window.location and trigger an alert.

I found these two threads to be very helpful:

Jorge Navarro
  • 574
  • 5
  • 2
1

You are sending the response first and then trying to redirect,that is causing the error as the connection will be closed once response is sent.

Try to use 'next' middleware in the post callback like

    app.post("auth",(req,res,next)=>{
    /* Your auth logic and in the else part use next for redirection */ 

    next('redirectionRoute') 

/* Or you can keep res.redirect() and remove the res.send() in else and use appropriate route handler for the redirect route - This is better way * /
    })
Sm Srikanth
  • 1,992
  • 1
  • 10
  • 10