Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Middleware #174

Closed
3rd-Eden opened this Issue Mar 14, 2014 · 6 comments

Comments

Projects
None yet
4 participants
Owner

3rd-Eden commented Mar 14, 2014

This issue discusses the middleware feature that will be added in the next iteration of Primus. We already have a plugin infrastructure in place which allows people to modify the Primus client and and server components but these plugins can not interact or intercept requests before they are passed in to the transformers themselves. By creating a middleware layer that is ran before we pass of the requests to the transformers we can build much more powerful and deeply integrated applications on top of primus.

As the plugins already make use of the use method which is frequently used by application frameworks that implement middleware support we have to pick a different name to add these kind of middleware layers. I want to suggest using the name before for middleware as all this functionality is ran before anything else is executed. It would look something like this:

primus.before('session', require('connect').session)
      .before('cookies', require('cookies').connect);

The method will be chainable and force middleware layers to be named before they can be stored. The reason for this is that we want to be able to enable, disable and remove middleware layers as well.

This middleware layer also allows us to clean up some of the internals of Primus as we could transform the following functionality into a middleware layer:

  • Access Control
  • Authorization
  • Serving of the /primus/primus.js
  • Serving of the /primus/spec

As these will be implemented as middleware layers they could be disabled by developers or even overridden if the community comes up with a better way of doing these.

primus.disable('spec');

This would disable the middleware layer that is registered for the spec. The middleware eco system currently forces a next param to the given function:

primus.before('middleware', function (req, res, next) { 
  req.cookies = cookieparser(req);
  next();
});

This is a lot of pointless overhead for middleware that can be implemented synchronously. We can add a little length check on the given function to see the amount of params they accept and see if we need to process it async or sync.

TL;DC/TL;DR

  • primus.before for adding middleware
  • primus.enable for enabling a previously disabled middleware
  • primus.disable disable added middleware
  • primus.remove remove a middleware layer completely.

@3rd-Eden 3rd-Eden added this to the 2.1 milestone Mar 14, 2014

pocesar commented Mar 14, 2014

+1 for checking the need (or not) of asynchronous call, just a nuisance when augmenting the request.

while we are at it, maybe could implement a priority like AngularJS has for directives, to ensure that one middleware will execute before others that are already set?

Owner

3rd-Eden commented Mar 14, 2014

I guess we could do something like:

primus.before('middleware', reference, { priority: 1 })

But you could just specify them your self in the correct order.

Member

lpinca commented Mar 15, 2014

If we can guarantee that the order of execution will respect the order of insertion, i wouldn't add the priority option, it will only be unneeded complexity imho.

I think that a priority based definition, as @pocesar mentioned, is an alternative to before. Using both just adds to confusion in my opinion. However, if we opt for a priority like angular does, then we could use a single interface for using middlewares.

primus.use('middleware', reference) // defaults to 0 and the order is undefined in this case
primus.use('middleware', reference, { priority: 100 }) // higher value runs first

Angular also supports a terminal priority to define a directive as the last one to execute on a given priority value, which is an interesting feature that can be added at a later point.

pocesar commented Mar 17, 2014

I think that's a good proposition @ruimarinho, since it would be backward compatible, since no older code uses the third parameter. but Primus would have to differentiate between what is a middleware and what's a plugin, or maybe there shouldn't be any difference at all, just the "priority queue" itself

Owner

3rd-Eden commented Mar 25, 2014

Landed in master. I decided not to implement priority as that would have complicated the a lot which is not worth it in my opinion. The middlewares are ran in order of insertion, so if you need a middleware layer to run before layer x it's up to the user to add it in the correct order.

@3rd-Eden 3rd-Eden closed this Mar 25, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment