Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Support middleware injected by AppDynamics.
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
commit edb8dbc517818baf10fb8e41cd57b061775c0ff1
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