0

I am making a "create an account" form. After the user submits it, the server makes sure fields are not empty and username is not taken (docs stored in MongoDB). In case of mistake(s), I want to send back as a response the mistake.

HTML below:

    <form action="/createaccount" id="myform" method="POST">

    <label>Enter your first name</label>
    <input type="text" placeholder="First name" name="firstname">

    </br><label>Enter your last name</label>
    <input type="text" placeholder="Last name" name="lastname">

    </br><label for="uname">Enter a username</label>
    <input type="text" placeholder="Username" name="username">

    </br><label for="psw">Enter a password</label>
    <input type="password" placeholder="Password" name="password">

    </br><button type="submit">Create Account</button>
    <div id="error"></div>


</form>

Node.js server below:

app.post('/createaccount', (req, res) => {
    new_username = req.body.username;
    new_password = req.body.password;
    new_firstname = req.body.firstname;
    new_lastname = req.body.lastname;

    MongoClient.connect(url, (err, client) => {
        if (err) return console.log(err)
        db = client.db('entelligence')

        var myobj = {
            firstName: new_firstname,
            lastName: new_lastname,
            username: new_username,
            password: new_password
        };

        var match = false;
        var empty = false;
        var error_string = "";
        for (var i = 0; i < array.length; i++) {
            console.log(array[i].username);
            if (array[i].username == new_username) {
                match = true;
            }
        }

        if (match) {
            error_string = "Username is  already taken. "
        };
        if (new_firstname == '' || new_lastname == '' || new_username == '' || new_password == '') {
            error_string += "Field(s) cannot be empty";
        }
        console.log(error_string);

        if (error_string == "") {
            db.collection("users").insertOne(myobj, function(err, res) {
                if (err) throw err;
                console.log("1 document inserted");
            });
            res.redirect('/');
        }

        res.send(error_string);

    })
})

When I press on create account, I get "can't set headers after they are sent" error, but I can't find where I sent more than 1 response for 1 request. Also, if I make a mistake (i.e. leave a field blank), I get directed to /createaccount where I get a text with the correct mistake. I don't want to load any page in case of a mistake. I just want an error to show on the page of the form. Anyone has an idea on how to do it?

Alain Daccache
  • 125
  • 1
  • 12
  • Use [a validator](https://validator.nu/)! Your line break elements have end tags (which are forbidden) but no start tags (which are mandatory)! – Quentin Jul 24 '18 at 10:35

1 Answers1

1

This is to do with when the headers on the response are being set on the response. This answer has some good explanations on why this happens.

This often occurs when you have multiple res.sends or res.redirects being called, try and return them to prevent this:

app.post('/createaccount', (req, res) => {
    new_username = req.body.username;
    new_password = req.body.password;
    new_firstname = req.body.firstname;
    new_lastname = req.body.lastname;

    MongoClient.connect(url, (err, client) => {
        if (err) return console.log(err)
        db = client.db('entelligence')

        var myobj = {
            firstName: new_firstname,
            lastName: new_lastname,
            username: new_username,
            password: new_password
        };

        var match = false;
        var empty = false;
        var error_string = "";
        for (var i = 0; i < array.length; i++) {
            console.log(array[i].username);
            if (array[i].username == new_username) {
                match = true;
            }
        }

        if (match) {
            error_string = "Username is  already taken. "
        };
        if (new_firstname == '' || new_lastname == '' || new_username == '' || new_password == '') {
            error_string += "Field(s) cannot be empty";
        }
        console.log(error_string);

        if (error_string == "") {
            db.collection("users").insertOne(myobj, function(err, res) {
                if (err) throw err;
                console.log("1 document inserted");
            });
            return res.redirect('/');
        }

        return res.send(error_string);

    })
})
OliverRadini
  • 6,238
  • 1
  • 21
  • 46
  • Thanks that is clear now :) I'm still wondering how to read that response in the html (onsuccess: function() ...) where can I put onsuccess with a POST method in a form? – Alain Daccache Jul 24 '18 at 10:42
  • It isn't easy to do if you're doing a proper form submit, it can be preferable to send the post request manually and handle it there. This has more information: https://stackoverflow.com/questions/374644/how-do-i-capture-response-of-form-submit – OliverRadini Jul 24 '18 at 10:48