From c7a1246c432aa19cc37088fb223ed29182590182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= Date: Wed, 22 Sep 2021 18:36:45 +0200 Subject: [PATCH] Support middleware injected by OpenTelemetry OpenTelemetry injects a proxy object into the router stack, which it uses for its tracing. 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. Made it more generic to just test if shimmer is used to wrap the handler --- lib/server-app.js | 4 +++- test/app.test.js | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/server-app.js b/lib/server-app.js index fcb8bb14..a9a4df9c 100644 --- a/lib/server-app.js +++ b/lib/server-app.js @@ -228,8 +228,10 @@ proto._findLayerByHandler = function(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; + const isShimmer = this._router.stack[k].handle['__wrapped'] && + this._router.stack[k].handle['__original'] === handler; - if (isOriginal || isNewRelic || isAppDynamics) { + if (isOriginal || isNewRelic || isAppDynamics || isShimmer) { return this._router.stack[k]; } else { // Aggressively check if the original handler has been wrapped diff --git a/test/app.test.js b/test/app.test.js index c320a6d1..c907d61e 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -145,6 +145,27 @@ describe('app', function() { done(); }); }); + + it('allows handlers to be wrapped by shimmer (ex: opentelemetry) on express stack', + function(done) { + const myHandler = namedHandler('my-handler'); + const wrappedHandler = function(req, res, next) { + myHandler(req, res, next); + }; + wrappedHandler['__wrapped'] = true; + wrappedHandler['__original'] = myHandler; + app.middleware('routes:before', wrappedHandler); + const 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) {