skafander skafander - 7 days ago 4
Javascript Question

NodeJS - store session data per HTTP request in a "global" variable

There is a similar thread that is currently two years old, and it pretty much sums up what I want.

To give you an example, for the C# developers there is a single Session object which stores user's session and is accessible anywhere, in each class, .dll, you name it. It's stored per-request.

I need basically the same thing. My users have simple permissions, they are either admins or have roughly 5 assigned elements. I'm storing these 5 elements in an access token, so basically in the first middleware I have an array of ids which are user's permissions.

What I want is not to pass a

permissions
object around, especially not to pass them to service/DAL layers which are responsible for querying the database since it's pretty ridiculous for
getAllCities
function to receive
permissions
object and a callback as parameters. Or whatever object for that matter.

I cannot store the values in global variables since the globals are, well, global. I don't want to pass the variables to each function, so I would probably fall back to rounding the databases for user's permissions per each call, but that's just.. Meh.

I also don't want to mess to much with dozens of libraries etc., because I believe this is a common problem that people stumble upon and I wonder what are the best solutions.

On the thread linked above there is a robust solution which I would frankly want to avoid. Everything I've used in Node has been plug-and-play, and implementing custom middlewares and pipelines for this "small" thing seems like an overkill.

Two years later, is there a better solution out there to this problem?

Answer

You would typically use something like express-session to manage a session for each user and then each incoming request would automatically have access to that session object for that user in the request handler. You can then store any user-specific information in that session object.

Any functions that you want to execute in a given request should either be passed the request object (from which they can get access to the session) or just pass them the session object or some user-specific object you pulled out of the session. In node.js the place for user-specific information is in the request object. There is no "global" space to store it that all other functions can access it.

If you want a function to be able to access request or session specific data, then pass that data to the function. That's how it works. If this appears to be a problem to you, then you have to rethink how your code is architected and perhaps use objects/methods that can maintain state more easily.

node.js does not have a thread per request that can have it's own thread state. Instead, in an http server, you use the request object as the core state for a given request and you pass it to functions that need it. Or, if you're using a user session, you can extract that from the request object and then pass the session around as needed.

I don't want to pass the variables to each function, so I would probably fall back to rounding the databases for user's permissions per each call, but that's just.. Meh.

It sounds to me like too much of your code is just plain functions rather than methods on an object. If you think of your code as a user object that has methods on it, then you can form a user object in the initial request and then call methods on that user object for most things you would want to do that are user-specific. The user object then is a nice simple repository for user-specific information (such as permissions) and ALL methods on the object will have access to it without having to pass it to every function.

I repeat, if passing the user state around seems like a burden, then it's probably because your code is not architected in a way that makes it easy. Rather than looking for a work-around for something that is not the way node.js works, you should think about architecting your code to make these kinds of things easy so your architecture more closely matches the needs of your code given the way the underlying system works.

implementing custom middlewares and pipelines for this "small" thing seems like an overkill.

Session middleware is not a small thing. It's core to any application that maintains user-specific data across requests and wants easy access to it on each new request from that same user. It's generally how you manage user state in node.js.

To give you an example, for the C# developers there is a single Session object which stores user's session and is accessible anywhere, in each class, .dll, you name it. It's stored per-request.

That simply isn't how node.js works at the lowest architectural level. And, the sooner you realize that and start designing your code to align with the way node.js actually works (rather than the way some other system works), the sooner you will find node.js coding flows naturally. It's something new to learn, not to be avoided or worked-around.