7
//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

codefreaK
  • 3,584
  • 5
  • 34
  • 65
  • this is not any answer to your question, but a suggestion: wouldn't it be easier to handle the add to cart functionality on the client side, and then send the cart data to the server when they go through checkout? – George Mar 24 '18 at 17:45
  • I could easily do work around but I want to find issue why once set cart object gets removed from session and where it gets removed and I want to use inspect to work the flow of the http requests .I tried a simple alternative instead of storing objecting req.session I stored in req.app.locals. and did the thing but what is causing this bug is still unknown . – codefreaK Mar 24 '18 at 17:48
  • if you are requiring express-session you also need to `app.use(session)` it – George Mar 24 '18 at 17:49
  • What I was really surprised about was that there is atleast 10-15 youtube tutorial videos on node inspector where upon running with inspect flag shows both script and the whole project and you can set the breakpoint where you want in those files but thats not case with me and no clue what and why is all this happening – codefreaK Mar 24 '18 at 17:50
  • I had already done that earlier see the edit .I did not add that code because I thought it was obvious when writing about session it had to be initialized – codefreaK Mar 24 '18 at 17:51
  • try using a different path when doing the command `node --inpect`, instead of just `app.js` maybe the folder ? `./` or up a directory `../` I have not used node inspector before though. If you could show your directory structure? do you start the app with `node app.js` ? – George Mar 24 '18 at 17:54
  • yes I start with it – codefreaK Mar 24 '18 at 17:56

2 Answers2

2

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.

mootrichard
  • 3,581
  • 13
  • 25
  • and about the inspect debugger part can u elaborate on the question – codefreaK Mar 28 '18 at 07:47
  • https://stackoverflow.com/questions/26178939/stumped-implementing-express-session-variables-as-an-array check this out I just googled if its possible or not it seems possible .See if it was not possible I shouldn't be able to do console.log(req.session.cart) and get the newly pushed array inside. but once I am redirected back it only has the flash message inside the session and no cart object thats the issue and for that I was asking how to properly set up inspector to find where the loss happens – codefreaK Mar 28 '18 at 07:59
  • Although I couldn't get your repo totally running, I could at least run the `/admin/` page and using Node Inspector could see all files and set breakpoints on your routes. I recommend running `node --inspect app.js` and opening Chrome and inspecting the page to find the "Dedicated DevTools for Node" in the top left of your console (should be a green hexagon). You'll launch a dedicated console for your Node app where you can look at the sources and set your breakpoints. – mootrichard Apr 02 '18 at 17:43
1

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.

vorillaz
  • 6,098
  • 2
  • 30
  • 46