question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Implement middleware for responders / subscribers

See original GitHub issue

Certain functions such as auth or request decoration would make use of middlewares, as in, virtually everywhere (Express & co).

The following code…

responder.on('request', function(req, cb) {
    // do something;
});

should still work with a middleware:

responder.on('request', middleware, function(req, cb) {
    // do something if middleware allows
});

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:15
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
mr-kashifcommented, May 5, 2019

@dashersw I’ve come up with a pretty clear idea of middleware based on express which will require no breaking changes and still support callbacks.

src/components/responder.js

on(type, ...listeners) {
    super.on(type, (...args) => {
      let index = 0;
      const next = () => {
        const rv = listeners[index++](...args, next);

        if (rv && typeof rv.then == 'function') {
          const cb = args.pop();
          rv.then((val) => cb(null, val)).catch(cb);
        }
      };
      next();
    });
  }

Examples -

Requester

requester.send({
      type: 'ping',
    },
    (err, str) => {
      console.log(str);
    }
  );

Responder

responder.on(
  'ping',
  (req, cb, next) => {
    console.log('responder middleware 1 - doing auth stuff');
    next();
  },
  (req, cb, next) => {
    console.log('responder middleware 2 - rate limiter');
    next();
  },
  (req, cb, next) => {
    console.log('responder middleware 3 - the result');
    cb(null, 'pong');
  }
);

Output

> responder middleware 1 - doing auth stuff
> responder middleware 2 - rate limiter
> responder middleware 3 - the result
> pong

I’ll ready a PR if you find this helpful and after testing it a bit more. 😉

1reaction
QQpingcommented, Dec 18, 2018

Just from personal interest, here is a little function which enables a certain set of express-like features.

  • middleware functions without the need for the next() call at all
  • if middleware returns false, break chain of functions
  • if some middleware throws something, break chain and return message to requester
  • first argument is an object, not just the event type!
  • first argument can be expanded with e.g. userdata from auth middleware

src/components/responder.js

on() {
  var args = Array.from(arguments),
      type = args.shift();

	super.on(type, async (type, callback) => {
    		var error,
            request;
            
        if (typeof type === 'object') {
          request = type;
        } else {
          request = {
            type: type
          };
        }

    let index = 0;
    const next = () => {
      const layer = args[index++];

      try {
        // Execute the layer

        var result = layer(request);
        if (result === false) {
          // break the next() chain
          callback();
        }
        if (args.length === index) {
          // last function called. time to return data
          callback(result);
        }
        if (result === undefined) {
          // no break, still not last function?
          // let's execute the next()
          next();
        }
      } catch(error) {
        callback(error);
      }
    };

    next();
	});
}

the requester example:

spotlightRequester.send({ type: 'latest', error: true }, (res) => {
  console.log(res);
});
spotlightRequester.send({ type: 'latest', intercept: true }, (res) => {
  console.log(res);
});
spotlightRequester.send({ type: 'latest' }, (res) => {
  console.log(res);
});

the responder with middleware:

spotlightResponder.on('latest', function (request) {
  if (request.error) {
    throw "something";
  }
  if (request.intercept) {
    return false;
  }
} , function(request) {
  console.log('result func ' + JSON.stringify(request));
  return { test: 1 };
});

and the output from the requester

>something
>null
>{ test:1 }

It is by far just a proof of concept, not clean and only tested on my side. It is just an idea how to solve the implementation of middleware and I am aware of the fact, that this implementation restructures the responder process.

Edit: merged actual request object from requester with the request object for the middleware.

Read more comments on GitHub >

github_iconTop Results From Across the Web

middleware-responder examples - CodeSandbox
Learn how to use middleware-responder by viewing and forking example apps that make use of middleware-responder on CodeSandbox.
Read more >
implementation - Go Packages
Responder ; func PostMOM(params monitoring_machine.PostMoMParams) middleware.Responder; func SubscribeES(params subscribers.
Read more >
How to implement StackMiddleware for a redirection correctly?
How do I use my redirection code (which I know works) with this StackMiddleware class so I can intercept the page cache?
Read more >
rabbus-custom - npm Package Health Analysis | Snyk
Rabbus.Subscriber; Rabbus.Responder. Extending Rabbus w/ Middleware. Rabbus message Producers and Consumers use a middleware system that allows you to extend ...
Read more >
rabbus - npm
Rabbus.Subscriber; Rabbus.Responder. Extending Rabbus w/ Middleware. Rabbus message Producers and Consumers use a middleware system that allows you to extend ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found