Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to track req.session variable with node-inspector to understand how a session object gets removed from request.session

//Initializing session 

app.use(session({

  secret: 'keyboard cat',
  resave: true,
  saveUninitialized: true
  //cookie: { secure: true }
}));

I was creating a shopping cart and came across a problem , I was setting cart object in session

req.session.cart = [];

//then

req.session.cart.push({
                    title : p.title,
                    price : p.price,
                    image : '/static/Product_images/'+p._id+'/'+p.image,
                    quantity:quantity,
                    subtotal : p.price

                });

after that I tried consoling that and I was getting the session variable with cart object inside it but after that while I tried setting it to app.locals.cart for using it with ejs , by trying to get req.session from inside a get method of the express module but the req.session.cart gives undefined.

app.use(require('connect-flash')());
app.use(function (req, res, next) {
  res.locals.messages = require('express-messages')(req, res);

 // console.log("New cart variable");
  //console.log(req.session);
  //console.log(req.locals);
  //console.log(req.app.locals.cart);

  if(req.session.cart!=="undefined"){
    app.locals.cart=[];
    app.locals.cart = req.session.cart ; 
  }
  next();
});

I was unable to understand why the session variable was losing the cart object

after going through some of questions in StackOverflow I found nothing that solves my dilemma .So I decided to stop using simple console.log but instead I decided to use the nodejs inspector and I installed I ran

node --inspect app.js

But the problem here I faced is that it limited its access to app.js itself the adding shopping cart functionality is in routes/cart.js

I wanted to track the flow of requests using nodejs inspector module and find out why the cart variable is removed from the session variable every time

So my question is of two part ,first part :- why is the sources folder only showing app.js instead of the whole project like in this simple tutorial

enter image description here I am not getting the project and files inside it to set debug points and source only has app.js as default loaded source

second part is why is cart object getting removed from session without any reason

EDIT:-

cart.js

I know one the first pass it will be undefined but on second path it will not be since it will be set by

var productModel =require('../models/products.js');
var categoryModel =require('../models/category.js');

module.exports=(app)=>{

    app.get('/add-to-cart/:id',function(req,res){

        console.log("Cart get started");
                var quantity,subtotal = 0;
                productModel.findOne({'_id':req.params.id},function(err,p){
                        //console.log("product consoled"+p);
                        if(err){
                            return console.log(err);
                        }
            if( typeof req.session.cart == "undefined"){

                //console.log("Session undefined check");

                quantity=1;
                req.session.cart = [];

                req.session.cart.push({
                    title : p.title,
                    price : p.price,
                    image : '/static/Product_images/'+p._id+'/'+p.image,
                    quantity:quantity,
                    subtotal : p.price

                });

                 console.log("#### The request var session inside cart function start");

                 console.log("#### The request var session var end");

                req.app.locals.cart=[];
                req.app.locals.cart.push({
                    title : p.title,
                    price : p.price,
                    image : '/static/Product_images/'+p._id+'/'+p.image,
                    quantity:quantity,
                    subtotal : p.price

                });
                //console.log(req.app.locals);
                //console.log("Session set ");

                //console.log(req.session.cart);

        console.log("Cart got set");
        console.log(req.session);

            }else{

                    var product = req.session.cart;
                    var productFound = false;
                        product.forEach(function(prod){


                            if(prod.title==p.title){
                                prod.quantity+=1;
                                prod.subtotal=prod.quantity*prod.price;
                                productFound=true;

                            }


                    });

                    req.session.cart=product;
                    if(!productFound){
                            quantity=1;
                            req.session.cart.push({
                            title : p.title,
                            price : p.price,
                            image : '/static/Product_images/'+p._id+'/'+p.image,
                            quantity:quantity,
                            subtotal : p.price

                        });
                    }
            }

        });     console.log("req.session.cart");
                console.log(req.session.cart);

                req.flash('success','product added to cart');
                res.redirect('back');
    });
}

EDIT 1:- I tracked the sessionId across the calls and found it to be same ruled about possibility of creation of new session but still what removes the cart object from session object remains a mystery

like image 759
codefreaK Avatar asked Mar 24 '18 17:03

codefreaK


People also ask

How do req sessions work?

The session corresponding to that sessionId is fetched from server and attached to req object as req. session. It gives a feel that we are getting session from client side, but actually it is the work of middleware to attach session object to req object by getting the cookie from the client.

How do you check session is set or not in node JS?

server. js var express = require('express'); var session = require('express-session'); var app = express();

What is saveUninitialized in Express-session?

saveUninitialized : When an empty session object is created and no properties are set, it is the uninitialized state. So, setting saveUninitialized to false will not save the session if it is not modified. The default value of both resave and saveUninitialized is true, but using the default is deprecated.


2 Answers

Cookies can only hold strings, but you're trying to initialize your cookie as an array and then push objects into it. A cookie will only do a basic "key":"value".

req.session.cart = {
  title : p.title,
  price : p.price,
  image : '/static/Product_images/'+p._id+'/'+p.image,
  quantity:quantity,
  subtotal : p.price
}

If you wanted to have it nested, that you'd likely have to use something JSON.stringify() to serialize it on a single key and deserialize it to look at the full object. So long as you keep your cookie below that max size.


Edit:

So although what I wrote holds true about cookies, it doesn't correctly address that express-sessions actually stores the data server-side and only stores the session id in the cookie.

In running an Express application using express-generator using node --inspect ./bin/www, you get the option to using Chrome's native NodeJS inspector. You should be able to view sources from the dedicated Node Inspector and see your entire directory from there.

Without seeing your full application structure, its hard to determine why you would only be seeing your app.js file, since Node will include all referenced files when inspecting. Presumably, the reason you're not seeing your routes is because you're passing your application to them, rather than including the routes within your main application (see below).

const indexRouter = require('./routes/index');
const cartRouter = require('./routes/cart');

const app = express();

app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true
//cookie: { secure: true }
}))

app.use('/', indexRouter);
app.use('/cart', cartRouter);

The only way that I could replicate your issue of the cart constantly disappearing was if I was using http and had cookie: { secure: true } not commented out.

like image 157
mootrichard Avatar answered Oct 20 '22 22:10

mootrichard


You may use a Proxy object and track down any mutations taking effect within the session.

const debugHandler = {
  get: function(target, property) {
    console.log('getting ' + property + ' for ' + target);
    // property is index in this case
    return target[property];
  },
  set: function(target, property, value, receiver) {
    console.log('setting ' + property + ' for ' + target + ' with value ' + value);
    target[property] = value;
    // you have to return true to accept the changes
    return true;
  }
};
req.session.cart = new Proxy([], debugHandler);

throw new Error() while mutating the object will pop the exact stack trace.

like image 44
vorillaz Avatar answered Oct 20 '22 20:10

vorillaz