0

I will preface this by saying I understand it is not best practice to put a userID in cookies, but this is an extremely simple application that is just supposed to display to the same user the number of times they have visited the site, so I'm just rolling with this implementation to keep things simple.

I'm using express, node, and mongoDB to handle this. What I'm trying to do is create and save a new instance of my User class, and then in the promise chain (where the Mongo ObjectID is returned), I'd like to write that ID to cookies so I can keep track of how many times they have come to the site.

It seems like I am receiving the Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers because I am trying to set cookies in the then statement which is completed after the headers are already sent off. I don't really understand this though, because I don't call setHeaders anywhere else.I have thought about creating a randomly generated number within the server, but that seems clunky as I can't guarantee it won't generate an existing ID. Does anyone know how I can get around this issue, or am I taking the complete wrong approach here?

User schema:

var UserSchema = new Schema({
  timesSeen: { type: Number, default: 0 },
});

The problem code

router.get("/", function (req, res, next) {
  // Read cookies
  let cookies = parseCookies(req.headers.cookie);
  // If userID cookies is not set, this is a new user (or one visiting from another browser)
  if (cookies.userID === undefined) {
    // Create a new instance of a user and save to mongoDB
    var newUser = new User({});
    newUser
      .save()
      .then((newUser) => {
        console.log("newUser");
        // This is the line that is giving me problems. 
        res.setHeader("Set-Cookie", [
          `userID=${newUser._id}`,
          "timesSeen=0",
        ]);
      })
      .catch((err) => {
        if (err) {
          console.log(err);
          return;
        }
      });
  } else {
    let timesSeen = Number(cookies.timesSeen) + 1;
    // let timesSeen = parseInt(cookies.timesSeen)++;
    // console.log("times", timesSeen);
    res.setHeader("Set-Cookie", [`timesSeen=${timesSeen}`]);
    res.render("index", {
      title: "Express",
    });
  }
});
user12457151
  • 853
  • 2
  • 12
  • 25
  • Does [this](https://stackoverflow.com/questions/16209145/how-to-set-cookie-in-node-js-using-express-framework) question solve your problem? It seems you are setting up the cookie in wrong way. – Apoorva Chikara Mar 16 '21 at 18:06
  • 1
    The code seems to be correct, can you share the all the routes? Could it be you are putting `router.get('/')` in front of other more specific route? – PKiong Mar 16 '21 at 18:07
  • @ApoorvaChikara, it is a requirement for my project that I do not use any modules to abstract away cookie useage. Unfortunately I cannot use the built in cookie modules :( – user12457151 Mar 16 '21 at 18:10
  • @Darkripper, my application only has a single Route. It's just a single page that tells you how many times you've been to the site. So does it seem weird to you that I am getting the error even though I'm not setting the header anywhere else in my code? I was wondering if the header gets set asyncrhonously somehow by itsself – user12457151 Mar 16 '21 at 18:12
  • 1
    Could you share the repo for me to take a look at it? – PKiong Mar 16 '21 at 18:15
  • You should use cookie parser if not using. This error, generally, comes in when you try to send res twice. It seems express sends an error by default when you are saving data to mongodb. Try checking the API response in Postman and add that in question code. – Apoorva Chikara Mar 16 '21 at 18:16
  • @ApoorvaChikara, yeah I will definitely be using that in the future, but this is an assignment and one constraint is that I do not use those modules. – user12457151 Mar 16 '21 at 18:30
  • @Darkripper, I don't really know why it ended up this way, but I figured it out on my own. Somehow my writeheader got moved in the branch I've been working in, I shifted that into the promise and now we're good! – user12457151 Mar 16 '21 at 18:47
  • Err... Its weird from my side as well, as everything is working, except for the rending of the views... glad it works out in the end tho – PKiong Mar 16 '21 at 18:50

0 Answers0