It's normal. Here's why:
HttpConext.Current
in Asp.net works because it is able to associate a particular worker thread with data, in this case the entire context of the request. This happens early in the page life cycle. Code can always ask, "what's my context" this way.
Nodejs, as it runs JavaScript in a single thread, has no equivalent to the thread local storage used by .NET. If only one request was processed at a time, the request
and response
values could be stored globally and accessed from anywhere.
However, as you know, the efficiency of NodeJs comes from the fact that the engine stays busy by doing async work in engine controlled threads. Further, as many async operations are IO, they are often waiting for the results of the IO operation to return. During that wait, the engine picks up work off the queue and executes it until the next async operation. Generally speaking, it would be difficult to predict what code was going to execute from the queue next. It wouldn't know the context of the code being executed without another NodeJS feature.
Without thread local storage to manage state, and without the ability to proper adjust global state for the "now" current request being served, the engine relies on JavaScript closures. These capture the context and scope, and are preserved through the execution of queued work and restored when the engine returns results to a block of code. Interestingly, Microsoft, had anonymous functions (reference) been available when Asp.Net was first created, could have followed a similar pattern to NodeJs.
So, there's not really a place to store a request's state globally without doing some association of the current JavaScript to the original request. A closure would be necessary. But, at that point, you might as well just pass the two values around, or combine them into a single context = { request : req, response : res }
. It would be normal to pass the values around as required.