Skip to content
New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Middleware #174

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

Middleware #174

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

Comments

@3rd-Eden
Copy link
Member

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
Copy link

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?

@3rd-Eden
Copy link
Member Author

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.

@lpinca
Copy link
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.

@ruimarinho
Copy link

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
Copy link

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

@3rd-Eden
Copy link
Member Author

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.

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

No branches or pull requests

4 participants