usersam
usersam

Reputation: 1235

nodejs express how to send response back to browser

I am trying to make a sign-in application in nodejs,using angularjs and express. From angularjs I am sending $http post request to server , where first it should check if the data is already present in MongoDB and send response back to client.

The Problem is, I am not able to configure the response with header information. Every time i am getting

Error: Can't set headers after they are sent.

or

MongoError: E11000 duplicate key error collection

Here is my app.js code.

app.post('/signin',function (req,res) {
    console.log('i recievied a get request in app.js = /signin');   
    console.log(req.body);
    db.users.findOne({$or: [{username: req.body.username}, {email: req.body.email}]},function (err, data){
    if ( err ) throw err;
    if (err) { res.send(err); return; }
    //res.json({ data: "Invalid Password" });
    if ( err ) {console.log('user found already in db'); console.log(err)};
    //res.json(data);
    //console.log('user found already in db')
    //res.redirect('/foo/bar');
    res.end('user found already in db');
    //res.send({ data: 'user found already in db' })
    //res.setHeader('Content-Type', 'application/json');
    //res.json({ a: 1 });   
    //res.writeHead(200, {'Content-Type': 'text/plain'});
    //res.send("jai shree ram");
    //res.end();
    //return;
    });

    db['users'].insert({
        username : req.body.username,
        firstname : req.body.firstname,
        lastname : req.body.lastname,
        email : req.body.email,
        password : req.body.password,
        createdAt : new Date(),
        role : "user",
        approvedBy : req.body.approver.username,
        status : "locked"
    },function (err, data){
    if ( err ) throw err;   
    //if ( err ) {console.log('user created in db'); console.log(err)}; 
    //res.json(data);
    //if (err) { res.send(err); return; }
    //res.json({ data: "Password" });
    res.end('user created in db');
    //res.send({ data: 'user created in db' })
    //res.setHeader('Content-Type', 'application/json');
    //res.json({ a: 1 });
    //res.end();
    //return;
    })

}); 

And from browser i am placing below request

$http({
            url: '/signin',
            method: "POST",
            data: $scope.SignInForm
            //headers: {'Content-Type': 'myapplication/json','charset' : 'utf-8'}
            })
            .then(function (res){
                console.log(res.data)                       
                },function (error){
                console.log(error)
            });

I tried out many things but not able to succeed.

Upvotes: 2

Views: 9857

Answers (2)

Yamini Chhabra
Yamini Chhabra

Reputation: 1149

The order of setting headers and sending data is wrong . First set headers and then send the response to front end.

res.setHeader('Content-Type', 'application/json');
res.send({ data: 'user created in db' })

Secondly your insert and find are running in parallel. Insert should only work if user is not found in db

app.post('/signin',function (req,res) {
    console.log('i recievied a get request in app.js = /signin');   
    console.log(req.body);
    db.users.findOne({$or: [{username: req.body.username}, {email: req.body.email}]},function (err, data){
        if (err) { 
            //Error Case (send to front end)
            res.send( error) 
        } else {
            if(data == null) {//Condition to check whether data exists or not
                db['users'].insert({
                    username : req.body.username,
                    firstname : req.body.firstname,
                    lastname : req.body.lastname,
                    email : req.body.email,
                    password : req.body.password,
                    createdAt : new Date(),
                    role : "user",
                    approvedBy : req.body.approver.username,
                    status : "locked"
                },function (err, data){
                    if ( err ) throw err;   
                    res.setHeader('Content-Type', 'application/json');
                    res.send({ data: 'user created in db' })
                });
            } else {
                 res.send(data)
            }
        }
    })
});

Upvotes: 5

Sravan
Sravan

Reputation: 18647

Because node js works asynchrounously your insert wont wait for findOne to complete so, you are getting duplicate error

You need to insert data in the callback function of findOne

app.post('/signin', function (req, res) {
    console.log('i recievied a get request in app.js = /signin');
    console.log(req.body);
    db.users.findOne({ $or: [{ username: req.body.username }, { email: req.body.email }] }, function (err, data) {
        if (data) {
            res.setHeader('Content-Type', 'application/json');
            res.end({ data: 'user found already in db' })
        }
        else {
            db['users'].insert({
                username: req.body.username,
                firstname: req.body.firstname,
                lastname: req.body.lastname,
                email: req.body.email,
                password: req.body.password,
                createdAt: new Date(),
                role: "user",
                approvedBy: req.body.approver.username,
                status: "locked"
            }, function (err, data) {
                if (err) {
                    res.setHeader('Content-Type', 'application/json');
                    res.end({ data: err })
                }
                res.setHeader('Content-Type', 'application/json');
                res.send({ data: 'user created in db' })

            })
        }
    });

}); 

Upvotes: 0

Related Questions