Skip to content

Commit edb8dbc

Browse files
Mike Limschnee
Mike Li
authored andcommitted
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.
1 parent b77907f commit edb8dbc

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

lib/server-app.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,15 @@ proto.middleware = function(name, paths, handler) {
221221
*/
222222
proto._findLayerByHandler = function(handler) {
223223
// Other handlers can be added to the stack, for example,
224-
// NewRelic adds sentinel handler. We need to search the stack
224+
// NewRelic adds sentinel handler, and AppDynamics adds
225+
// some additional proxy info. We need to search the stack
225226
for (var k = this._router.stack.length - 1; k >= 0; k--) {
226-
if (this._router.stack[k].handle === handler ||
227-
// NewRelic replaces the handle and keeps it as __NR_original
228-
this._router.stack[k].handle['__NR_original'] === handler
229-
) {
227+
const isOriginal = this._router.stack[k].handle === handler;
228+
const isNewRelic = this._router.stack[k].handle['__NR_original'] === handler;
229+
const isAppDynamics = this._router.stack[k].handle['__appdynamicsProxyInfo__'] &&
230+
this._router.stack[k].handle['__appdynamicsProxyInfo__']['orig'] === handler;
231+
232+
if (isOriginal || isNewRelic || isAppDynamics) {
230233
return this._router.stack[k];
231234
} else {
232235
// Aggressively check if the original handler has been wrapped

test/app.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,28 @@ describe('app', function() {
124124
});
125125
});
126126

127+
it('allows handlers to be wrapped as __appdynamicsProxyInfo__ on express stack',
128+
function(done) {
129+
var myHandler = namedHandler('my-handler');
130+
var wrappedHandler = function(req, res, next) {
131+
myHandler(req, res, next);
132+
};
133+
wrappedHandler['__appdynamicsProxyInfo__'] = {
134+
orig: myHandler,
135+
};
136+
app.middleware('routes:before', wrappedHandler);
137+
var found = app._findLayerByHandler(myHandler);
138+
expect(found).to.be.an('object');
139+
expect(found).have.property('phase', 'routes:before');
140+
executeMiddlewareHandlers(app, function(err) {
141+
if (err) return done(err);
142+
143+
expect(steps).to.eql(['my-handler']);
144+
145+
done();
146+
});
147+
});
148+
127149
it('allows handlers to be wrapped as a property on express stack',
128150
function(done) {
129151
var myHandler = namedHandler('my-handler');

0 commit comments

Comments
 (0)