regenerate session on db callback - node.js

I am trying to regnerate session on successful validation of user credentials.But the session doesn't get regenerated when the code is in db callback
app.post('/login',function(req,res){
var userName=req.body.userid.toLowerCase();
db.collection('credentials').findOne({'userName':userName},function(err,result){
req.session.regenerate(function (err) {
});
});
});
It works fine out side it
app.post('/login',function(req,res){
var userName=req.body.userid.toLowerCase();
req.session.regenerate(function (err) {
});
db.collection('credentials').findOne({'userName':userName},function(err,result){
});
});
Any ideas?

Looks like the mistake was on my part.The code was responding to the request right below the code i posted. Since these work in async, I guess the response was sent beofre the session was reset.
app.post('/login',function(req,res){
var userName=req.body.userid.toLowerCase();
db.collection('credentials').findOne({'userName':userName},function(err,result){
req.session.regenerate(function (err) {
});
res.send('welcome '+result.firstName+' '+result.lastName);
});
});
I moved the response inside the regenarte call back and it is working now.

Related

router.get inside router.post, can't reach router.get

am trying to have a router.get inside router.post, I need to compare the information provided by the user to the one in the database and then post it if it does not exists. The problem is the router.get is never reached. No errors, and postman keeps "sending request" with no end. Is it possible to have a router.get inside router.post?, if yes how?, If no, how do I get info from router.get to pass to router.post? I need to run the api from ..../new, and do all the work from there. Thanks in advance
//register
router.post('/new', (req, res, next)=>{
console.log("jumped out");
var user_id, password0, password1;
user_id = req.body.user_id;
password0 = req.body.password0;
password1 = req.body.password1;
console.log(password1);
//retrieving usernames to check if it exists
router.get('/accounts', (req, res, next)=>{
console.log("in here");
detail.find(function(err, accounts){
//looping through usernames
for (var i=0; i<accounts.length; i++){
if (accounts[i].user_id === user_id){
res.json({msg: 'Username taken'});
}
else if(i == (accounts.length-1)){
if (password0 === password1){
let newAccount = new account({
user_id: this.user_id,
password: this.password0
});
newAccount.save((err, account)=>{
if(err){
res.json({msg: 'failed to create account'});
}
else{
res.json({msg: 'Account created successfully'});
}
});
}
else if (password0 !== password1){
res.json({msg: 'Password mismatch'});
}
}
}
//res.json(accounts);
});
});
});
I think the issue here is that you have a misunderstanding about what router.get is doing. It sounds like you want to accept a POST request from the user, then make a get request to check if the data already exists, and if not, then update your database.
If this is the case, the inner GET should actually use something like axios to make a request. You can make an axios request like this:
const axios = require('axios');
// Make a request for a user with a given ID
axios.get('/user?ID=12345')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
If you are actually trying to accept a second request from the user after the POST, then you should NOT do that. Users should only make one request for one action. You'll run into all kinds of issues down that path.
Turns out you can still retrieve data with only .POST, without having .GET. Removing the line having router.get, fixed the problem.
router.get('/accounts', (req, res, next)=>{

Express.js Routing error: Can't set headers after they are sent

I'm not really sure why I'm getting this error. It's a simple API built on express.js to be able to add and remove posts. The error occurs when I trigger the delete router. I've read that the error typically happens when there are two callbacks, however, I don't seem to be able find any double callbacks.
_http_outgoing.js:344
throw new Error('Can\'t set headers after they are sent.');
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
at ServerResponse.header (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:718:10)
at ServerResponse.send (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:163:12)
at ServerResponse.json (/Users/bounty/Projects/_learning/react-express/node_modules/express/lib/response.js:249:15)
at /Users/bounty/Projects/_learning/react-express/server/routes/posts.js:86:9
at nextTickCallbackWith0Args (node.js:452:9)
at process._tickCallback (node.js:381:13)
Here is my posts.js router:
module.exports = function(router) {
var Post = require('../models/post.js');
// middleware for the api requests
router.use(function(req, res, next) {
// do logging
console.log('something is happening.');
next(); // make sure we go to our next route and don't stop here
});
// test route to make sure everything is working (accessed at GET http://localhost:8080/api)
router.get('/', function(req, res) {
res.json({ message: 'hooray! welcome to our api!' });
});
// all routes here
// routes that end in /posts
router.route('/posts')
// create a Post (accessed at POST http://localhost:7777/api/posts)
.post(function(req, res) {
var post = new Post();
post.postTitle = req.body.postTitle; // set the post name (comes from request)
// save post and check for errors
post.save(function(err) {
if (err)
res.send();
res.json({ message: 'post created!' });
});
})
// get all Posts (accessed at GET http://localhost:7777/api/posts)
.get(function(req, res) {
Post.find(function(err, posts) {
if (err)
res.send();
res.json(posts);
});
});
// routes that end in /posts for specific id
router.route('/posts/:post_id')
// get the post with that id
.get(function(req, res) {
Post.findById(req.params.post_id, function(err, post) {
if (err)
res.send(err);
res.json(post);
});
})
// update the post with that id
.put(function(req, res) {
Post.findById(req.params.post_id, function(err, post) {
if (err)
res.send(err);
post.postTitle = req.body.postTitle;
// save the post
post.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'post updated!' });
});
});
})
// deletes the post with that id
.delete(function(req, res) {
Post.remove({
_id: req.params.post_id
}, function(err, post) {
if (err) {
res.send(err);
}
res.json({ message: 'post deleted!' });
});
});
}
You need to add the 'return' so that you don't reply twice.
// save post and check for errors
post.save(function(err) {
if (err) {
return res.send();
}
res.json({ message: 'post created!' });
});
That particular error message is pretty much always caused because of a timing error in the handling of an async response that causes you to attempt to send data on a response after the response has already been sent.
It usually happens when people treat an async response inside an express route as a synchronous response and they end up sending data twice.
One place I see you would get this is in any of your error paths:
When you do this:
// save post and check for errors
post.save(function(err) {
if (err)
res.send();
res.json({ message: 'post created!' });
});
If post.save() generates an error, you will do res.send() and then you will do res.json(...) after it. Your code needs to have a return or an else so when there's an error you don't execute both code paths.
So, this can happen in Express when attempting to send res.end twice which res.send and res.json both do. In your if(err) block you'll want to return res.send() as res.send runs asynchronously and res.json is getting called as well. I'm wondering if you're getting an error in your delete route? Hope this helps.
Best!
You are using res.send() or res.json() twice in the same request
this send the headers first, followed by body of the response and then headers again.
req.next is usually not a function, next is rather passed as a third argument of the middleware. Use that if you want to drop to the next middleware. (assuming you are using Express framework)
Just for the sake of completeness I will also mention that:
Sometime problem may be in a the middleware you may be using by calling
app.use.
After checking for obvious errors as mentioned in previous answers:
You should remove all the app.use statement then reintroduce them one by one, to find problematic module.
If you are using res.send() inside any loop, then you need to break it after the use of res.send(). So that it won't allow resetting of the res headers again and again.
for e.g :
for(){
if(){
res.send();
break;
}
else(){
res.send();
break;
}
}
In my case this is the problem and I solved it like this.
Hope it may help someone in future.
Thanks
For a quick fix you can just check res.finished before calling res.send():
if (!res.finished)
res.send()

app.render() not displaying in browser

I'm trying to use app.render() to display a jade file in the browser. In the following code, the html is displayed to the console correctly, but the browser never shows the related file.
app.render('unavailable', {title: 'Unavailable'}, function(err, html){
console.log(html);
});
EDIT:
I have this handler:
app.get('/unavailable', display.unavailable);
Then beneath this code in the same file (app.js) I have this:
sql.open(connStr, function(err, sqlconn){
if(err){
console.error("Could not connect to sql: ", err);
else
conn = sqlconn; //save the sql connection globally for all client's to use
});
So, what I want to happen is when the err happens with the SQL connection, the /unavailable handler is executed and a static html page is displayed that says the service is down. However, because the error occurs on the server, and not the client, I don't have access to a response object at that time. I'm trying to artifically manufacture the client 'redirecting' to /unavailable in their browser to see the message.
Obviously you don't send the html to the browser. Use res.render inside a route without callback, i.e.
res.render('unavailable', {title: 'Unavailable'});
or send the result of rendering like here:
app.render('unavailable', {title: 'Unavailable'}, function(err, html){
console.log(html);
res.send(html);
});
Read more about the difference here:
What's the difference between "app.render" and "res.render" in express.js?
save a global var sqlOK = false, set it in sql.open callback, and redirect to /unavailable if you get a request while sqlOK is not true. you were also missing brackets around the else statement.
var sqlOK = false;
app.get('/unavailable', display.unavailable);
app.get('*', function(req, res, next){
if(!sqlOK){
return res.redirect('/unavailable');
//return res.send(500)
};
next();
});
sql.open(connStr, function(err, sqlconn){
if(err){
console.error("Could not connect to sql: ", err);
} else {
conn = sqlconn; //save the sql connection globally for all client's to use
sqlOK = true
}
});

Nodejs inserting data to mongodb. It takes too much time

Hi i am developing nodejs application. I am inserting data to mongodb but my page always in 'loading' mode. But strange thing is my data inserted to mongodb immediately but page load not stopping. My code is shown below:
app.post('/Management/Post/New',function(req, res){
new Post({
title:req.body.post.title,
body:req.body.post.body,
keywords:req.body.post.keywords
}).save(function (err, docs){
if(err) {
return res.render(__dirname + "/views/createpost", {
title: 'Yeni Gönderi Oluştur',
stylesheet: 'postcreate',
error: 'Gönderi oluşturulurken bir hata ile karşılaşıldı'
});
}
console.log('Gönderi oluşturuldu');
});
});
Have no idea.
You only send a response when there is an error. If there's no error, you server never sends anything back: that's why the page seems to always be loading.
You need to send a response when you have no error, like this:
.save(function (err, docs){
if(err) { // Executed when there was an error with Mongo
return res.render(...);
} else { // Executed when everything is fine
return res.render(...);
}
});
You aren't handling the success scenario except for a console.log. You need a res.render() or res.redirect() on success, not just error

How do I return an error message to the client after failed Mongoose validation in Express

I have a very basic POST route that creates a new user out of the given data.
Here's how I save it:
app.post('/create', function(req, res){
var firstUser = new models.User(req.body);
firstUser.save();
});
My Mongoose User schema has a few validation options, which work. If I pass the wrong data, validation fails and the user isn't created.
But there's a problem: Mongoose's save() function is asynchronous, so how do I let the client now the validation failed?
The post function will be done by then.
You should have a look at Mongoose documentation. Because save method is asynchronous it takes a callback as parameter. This is where you should check for errors.
app.post('/create', function(req, res){
var firstUser = new models.User(req.body);
firstUser.save(function (err) {
if (err) {
res.send(500, { error: 'Saving first user failed!' });
} else {
res.send({ success: 'Saved!' });
}
})
});

Resources