Skip to content

Commit

Permalink
Support middleware injected by AppDynamics.
Browse files Browse the repository at this point in the history
AppDynamics injects a proxy object into the router stack, which it
uses for its network analysis.  This is similar to how NewRelic
adds a sentinel handler to the router stack. This commit adds a
similar workaround so that loopback can find the original layer.
  • Loading branch information
Mike Li authored and mschnee committed Jan 25, 2019
1 parent b77907f commit edb8dbc
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 5 deletions.
13 changes: 8 additions & 5 deletions lib/server-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,15 @@ proto.middleware = function(name, paths, handler) {
*/
proto._findLayerByHandler = function(handler) {
// Other handlers can be added to the stack, for example,
// NewRelic adds sentinel handler. We need to search the stack
// NewRelic adds sentinel handler, and AppDynamics adds
// some additional proxy info. We need to search the stack
for (var k = this._router.stack.length - 1; k >= 0; k--) {
if (this._router.stack[k].handle === handler ||
// NewRelic replaces the handle and keeps it as __NR_original
this._router.stack[k].handle['__NR_original'] === handler
) {
const isOriginal = this._router.stack[k].handle === handler;
const isNewRelic = this._router.stack[k].handle['__NR_original'] === handler;
const isAppDynamics = this._router.stack[k].handle['__appdynamicsProxyInfo__'] &&
this._router.stack[k].handle['__appdynamicsProxyInfo__']['orig'] === handler;

if (isOriginal || isNewRelic || isAppDynamics) {
return this._router.stack[k];
} else {
// Aggressively check if the original handler has been wrapped
Expand Down
22 changes: 22 additions & 0 deletions test/app.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,28 @@ describe('app', function() {
});
});

it('allows handlers to be wrapped as __appdynamicsProxyInfo__ on express stack',
function(done) {
var myHandler = namedHandler('my-handler');
var wrappedHandler = function(req, res, next) {
myHandler(req, res, next);
};
wrappedHandler['__appdynamicsProxyInfo__'] = {
orig: myHandler,
};
app.middleware('routes:before', wrappedHandler);
var found = app._findLayerByHandler(myHandler);
expect(found).to.be.an('object');
expect(found).have.property('phase', 'routes:before');
executeMiddlewareHandlers(app, function(err) {
if (err) return done(err);

expect(steps).to.eql(['my-handler']);

done();
});
});

it('allows handlers to be wrapped as a property on express stack',
function(done) {
var myHandler = namedHandler('my-handler');
Expand Down

0 comments on commit edb8dbc

Please sign in to comment.