Gathering detailed insights and metrics for loopback-context
Gathering detailed insights and metrics for loopback-context
Gathering detailed insights and metrics for loopback-context
Gathering detailed insights and metrics for loopback-context
@loopback/example-context
Standalone examples to illustrate features provided by @loopback/context
@loopback/context
Facilities to manage artifacts and their dependencies in your Node.js applications. The module exposes TypeScript/JavaScript APIs and decorators to register artifacts, declare dependencies, and resolve artifacts by keys. It also serves as an IoC container
uvm
Universal Virtual Machine for Node and Browser
@loopback/context-explorer
Visualize context hierarchy, bindings, configurations, and dependencies
npm install loopback-context
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
25 Stars
70 Commits
21 Forks
23 Watching
7 Branches
22 Contributors
Updated on 30 Nov 2023
JavaScript (100%)
Cumulative downloads
Total Downloads
Last day
1.9%
1,260
Compared to previous day
Last week
-4.5%
6,685
Compared to previous week
Last month
-2.1%
27,836
Compared to previous month
Last year
-12.4%
321,528
Compared to previous year
1
⚠️ LoopBack 3 has reached end of life. We are no longer accepting pull requests or providing support for community users. The only exception is fixes for critical bugs and security vulnerabilities provided as part of support for IBM API Connect customers. (See Module Long Term Support Policy below.)
We urge all LoopBack 3 users to migrate their applications to LoopBack 4 as soon as possible. Refer to our Migration Guide for more information on how to upgrade.
Current context for LoopBack applications, based on cls-hooked.
cls-hooked
module uses undocumented AsyncWrap
API that was introduced to Node.js relatively recently. While this new API seems to be more reliable than the old async-listener
used by continuation-local-storage
, there are still cases where the context (local storage) is not preserved correctly. Please consider this risk before using loopback-context.
when, a popular Promise
implementation, breaks context propagation. Please consider using the
built-in Promise
implementation provided by Node.js or
Bluebird instead.
Express middleware chains which contain a "bad" middleware (i.e. one which breaks context propagation inside its function body, in a way mentioned in this doc) especially if called before other "good" ones needs refactoring, in order to prevent the context from getting mixed up among HTTP requests. See usage below for details.
Discussion: https://github.com/strongloop/loopback-context/issues/17
In general, any module that implements a custom task queue or a connection pool is prone to break context storage. This is an inherent problem of continuation local storage that needs to be fixed at lower level - first in Node.js core and then in modules implementing task queues and connection pools.
$ npm install --save loopback-context cls-hooked
Make sure you are running on a Node.js version supported by this module
(^4.5
, ^5.10
, ^6.0
, ^7.0
, ^8.2.1
or ^10.14
). When installing, check the output of npm install
and make sure there are no engine
related warnings.
To minimize the likelihood of loosing context in your application, you should
ensure that cls-hooked
is loaded as the first module of your application, so
that it can wrap certain Node.js APIs before any other modules start using these
APIs.
Our recommended approach is to add -r cls-hooked
to node's list of
arguments when starting your LoopBack application.
$ node -r cls-hooked .
If you are using a process manager like strong-pm
or pm2
, then consult
their documentation whether it's possible to configure the arguments used to
spawn worker processes. Note that slc run
does not support this feature yet,
see strong-supervisor#56.
Alternatively, you can add the following line as the first line of your main application file:
1require('cls-hooked');
This approach should be compatible with all process managers, including
strong-pm
. However, we feel that relying on the order of require
statements
is error-prone.
To setup your LoopBack application to create a new context for each incoming
HTTP request, configure per-context
middleware in your
server/middleware.json
as follows:
1{ 2 "initial": { 3 "loopback-context#per-request": { 4 } 5 } 6}
IMPORTANT: By default, the HTTP req/res objects are not set onto the current context. You
need to set enableHttpContext
to true to enable automatic population
of req/res objects.
1{ 2 "initial": { 3 "loopback-context#per-request": { 4 "params": { 5 "enableHttpContext": true 6 } 7 } 8 } 9}
Once you’ve enabled context propagation, you can access the current context
object using LoopBackContext.getCurrentContext()
. The context will be
available in middleware (if it is loaded after the context middleware),
remoting hooks, model hooks, and custom methods.
1var LoopBackContext = require('loopback-context'); 2 3// ... 4 5MyModel.myMethod = function(cb) { 6 var ctx = LoopBackContext.getCurrentContext(); 7 ctx.get('key'); 8 ctx.set('key', { foo: 'bar' }); 9});
In order to workaround the aforementioned concurrency issue with when
(and
similar Promise
-like and other libraries implementing custom queues and/or
connection pools), it's recommended to activate context binding inside each
HTTP request or concurrent runInContext()
call, by using the bind
option, as
in this example:
var ctx = LoopBackContext.getCurrentContext({ bind: true });
With the option enabled, this both creates the context, and binds the access
methods of the context (i.e. get
and set
), at once.
Warning: this only works if it's the first expression evaluated in every
middleware/operation hook/runInContext()
call etc. that uses
getCurrentContext
. (It must be the first expression; it may not be enough if
it's at the first line). Explanation: you must bind the context while it's still
correct, i.e. before it gets mixed up between concurrent operations affected by
bugs. Therefore, to be sure, you must bind it before any operation.
Also, with respect to the "bad", context-breaking middleware use case mentioned in "Known issues" before, the following 2 lines need to be present at the beginning of the middleware body. At least the "bad" one; but, as a preventive measure, they can be present in every other middleware of every chain as well, being backward-compatible:
var badMiddleware = function(req, res, next) {
// these 2 lines below are needed
var ctx = LoopBackContext.getCurrentContext({bind: true});
next = ctx.bind(next);
...
The bind
option defaults to false
. This is only in order to prevent breaking
legacy apps; but if your app doesn't have such issue, then you can safely use
bind: true
everywhere in your app (e.g. with a
codemod, or by monkey-patching
getCurrentContext()
globally, if you prefer an automated fashion).
Warning: this only applies to application modules. In fact, if the module
affected by the concurrency issue is of this kind, you can easily refactor/write
your own code so to enable bind
. Not if it's a 3rd-party module, nor a
Loopback non-core module, unless you fork and fix it.
In advanced use cases, for example when you want to add custom middleware, you
have to add the context middleware at the right position in the middleware
chain (before the middleware that depends on
LoopBackContext.getCurrentContext
).
IMPORTANT: LoopBackContext.perRequest()
detects the situation when it is
invoked multiple times on the same request and returns immediately in
subsequent runs.
Here is a snippet using a middleware function to place the currently authenticated user into the context so that remote methods may use it:
server/middleware/store-current-user.js
1module.exports = function(options) {
2 return function storeCurrentUser(req, res, next) {
3 if (!req.accessToken) {
4 return next();
5 }
6
7 app.models.UserModel.findById(req.accessToken.userId, function(err, user) {
8 if (err) {
9 return next(err);
10 }
11 if (!user) {
12 return next(new Error('No user with this access token was found.'));
13 }
14 var loopbackContext = LoopBackContext.getCurrentContext();
15 if (loopbackContext) {
16 loopbackContext.set('currentUser', user);
17 }
18 next();
19 });
20 };
21};
server/middleware.json
1{ 2 "initial": { 3 "loopback-context#per-request": {} 4 }, 5 "auth": { 6 "loopback#token": {} 7 }, 8 "auth:after": { 9 "./middleware/store-current-user": {} 10 } 11}
common/models/YourModel.json
1var LoopBackContext = require('loopback-context'); 2module.exports = function(YourModel) { 3 ... 4 //remote method 5 YourModel.someRemoteMethod = function(arg1, arg2, cb) { 6 var ctx = LoopBackContext.getCurrentContext(); 7 var currentUser = ctx && ctx.get('currentUser'); 8 console.log('currentUser.username: ', currentUser.username); // voila! 9 ... 10 cb(null); 11 }; 12 ... 13};
This module adopts the Module Long Term Support (LTS) policy, with the following End Of Life (EOL) dates:
Version | Status | Published | EOL |
---|---|---|---|
3.x | End-of-Life | Jan 2017 | Dec 2020 |
1.x | End-of-Life | Aug 2016 | Apr 2019 |
Learn more about our LTS plan in the docs.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
0 existing vulnerabilities detected
Reason
Found 10/17 approved changesets -- score normalized to 5
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
license file not detected
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2024-11-18
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More