Catch all requests before individual route matches

685 views
Skip to first unread message

Brad Orego

unread,
Jun 5, 2013, 1:20:06 PM6/5/13
to ve...@googlegroups.com
I'm trying to find a way to keep my code DRY when it comes to authentication. Basically, I want a way to check all requests before they hit individual routes so that I can a) detect whether or not a cookie exists, and b) make sure the user's data is loaded locally before hitting routes (so the routes/templates can pull out user data).

I could check this in every single route in the application, but that's also a lot of repeating code. I've looked at the source and haven't found a way to do this, so any insight would be wonderful.

Language: Javascript
Version: 2.0.0-beta2

bytor99999

unread,
Jun 5, 2013, 2:07:14 PM6/5/13
to ve...@googlegroups.com
Currently, in our application. Every incoming request through the main eventLoop gets put onto the eventBus to our Security Module, where in that module it will do authentication, or if already logged in get the User Session data from Redis and add it to the request. Then send it back on the eventBus, to then be picked up by our "router" code.

Mark

Tim Fox

unread,
Jun 5, 2013, 2:23:07 PM6/5/13
to ve...@googlegroups.com
I'm not sure this is possible (in JS) without some really hacky code,
but it would be easy to add. Feel free to add a github issue :)

Paulo Lopes

unread,
Jun 5, 2013, 3:01:58 PM6/5/13
to ve...@googlegroups.com
Well, if you consider helper modules such as yoke you can do that.

Since yoke is a chain executor you can add middleware before the router middleware. However this is not 100% pure vert.x you need yoke.

Basically it would be something like this:

new Yoke(vertx)
  .add(new Middleware() {
    public void handle(YokeRequest request, Handler<Object> next) {
       // here do your validation, if ok
       next.handle(null);
       // on error
       request.response.end("Error!!!");
    }
  })
  .add(new Router()
   ...

Brad Orego

unread,
Jun 10, 2013, 11:00:27 AM6/10/13
to ve...@googlegroups.com
Thanks for the responses, all.


@Paulo - I've seen and appreciate Yoke, but I also think this isn't something you should need middleware to do. Also, I'm trying to keep this as simple as possible (for maintenance's sake, as I likely won't be the one maintaining this codebase after the project is complete)

Paulo Lopes

unread,
Jun 10, 2013, 2:39:32 PM6/10/13
to ve...@googlegroups.com
I would not really agree with that. I am not saying you should use yoke. I want to say that vert.x is supposed to be as simple as possible but not too simple. It does all the simple things it was designed to do, such as web servers that can in a high level handle all http verbs using the route matcher and this is good enough for say most of the folks using vert.x but for more complex examples you need to use the handler directly and do your stuff.

If you start requesting the route matcher to allow point cuts in its execution and triggering events before, after any action, then the complexity of the route matcher increases in a way that it may become not that useful for most folks.

This was the reason i had to start yoke. I saw the power of the base code and saw that it could be possible that some people need more than the route matcher. In this case and after fighting with the problem myself I got quite happy with the current implementation of yoke.

I think that if you do not want dependencies is fine (i am fond of that too) but i can also say that creating a class that can run before the route matcher is also a no brainer, start by extending the router matcher and override the handle(HttpServerRequest) method and call you stuff before...

I think that the extension would be the easiest and minimal code you would need to maintain, something like:

var server = vertx.createHttpServer();

var routeMatcher = new vertx.RouteMatcher();

// keep a ref to the original function
var handlerFn = rm.handle;

rm.handle = function (req) {
  // do the authentication step...
  ...
  // delegate again on the original function
  handlerFn.apply(rm, req);
}

server
.requestHandler(routeMatcher).listen(8080, 'localhost');

note that i might have the JS API wrong (since i am typing out of my head from the java API.

bytor99999

unread,
Jun 10, 2013, 5:57:59 PM6/10/13
to ve...@googlegroups.com
Paulo's approach here at the bottom is how we are doing our authentication call to our mod-security. All messages are first routed there, then the reply comes back, basically true or false, and if true move it along the normal path. Very simple and it doesn't cause you to have to find an add-on, AOP, or customizing Vert.x. It is using Vert.x the way that it was intended to be used.

I think when you digress from the normal design you end up with more difficult to maintain code.

Mark

Brad Orego

unread,
Jun 12, 2013, 5:45:37 PM6/12/13
to ve...@googlegroups.com
Paulo's snippet would be wonderful, and this would be a non-issue, if there were such a thing as "handle" on the RouteMatcher object in Javascript. I'm not asking for something crazy here that's going to kludge up vertx core (hence why Tim was like "Hey, submit a git request"), and I'm don't have any weird design patterns. When writing a server, I should be able to write a front-router to catch all of the requests and then decide what to do with them.

This isn't a vertx issue so much as it is a vertx JS issue. I'd be thrilled if what you're doing was possible in JS.

Tim Fox

unread,
Jun 13, 2013, 2:29:46 AM6/13/13
to ve...@googlegroups.com
I added this yesterday - see the github issue
>>> // keep a ref to the original functionvar handlerFn = rm.handle;

Tim Fox

unread,
Jun 13, 2013, 2:43:41 AM6/13/13
to ve...@googlegroups.com

Brad Orego

unread,
Jun 13, 2013, 10:47:19 AM6/13/13
to ve...@googlegroups.com
Hooray!

Now the question is can I just drop this mod into my current build (2.0.0-beta2) or do I have to rebuild the entire project from source? If the latter, um, how do I do that? :)

Brad Orego

unread,
Jun 13, 2013, 11:17:59 AM6/13/13
to ve...@googlegroups.com
Answer: I totally just dropped it in, though I probably did it wrong. Also, considering we'll be using this in production (running on a Windows box), I should probably have it built from source anyway

Tim Fox

unread,
Jun 13, 2013, 11:21:35 AM6/13/13
to ve...@googlegroups.com
This is just a change in the mod-lang-rhino project so (until we update
the langs.properties in vert.x-core) you can edit langs.properties in
your vert.x installation and point it at the latest snapshot of
mod-lang-rhino

Brad Orego

unread,
Jul 3, 2013, 9:43:29 PM7/3/13
to ve...@googlegroups.com
Hi all,

Not to necro a thread, but I've noticed some problematic behavior with this approach.

It's great at catching all the requests and doing something with them if need be (e.g. if the current request is unauthenticated), however it seems that there's something weird happening when making a request within the front-router and then trying to pass the request on to its respective RouteMatcher match - the req.bodyHandler() never fires.

Example:
(request made in front-router, rm.get('/')'s bodyHandler never fires
var vertx = require('vertx'),
console = require('vertx/console'),
client = vertx.createHttpClient().host('google.com'),
rm = new vertx.RouteMatcher();
rm.get('/', function(req) {
  console.log("rm1");
  req.bodyHandler(function (body) {
  console.log("rm2");
  req.response.end("Hello, World");
  });
});
vertx.createHttpServer().requestHandler(rm).requestHandler(function (req) {
console.log("front-router");
var request = client.get('/', function (resp) {
rm.call(req);
});
request.end();
}).listen(8080);
console.log("listening on 8080");
Console:
Brads-MacBook:example bradorego$ vertx run server.js
listening on
8080
front
-router
rm1


If you remove the request within the anonymous routematch function, everything seems to work fine...

Brads-MacBook:example bradorego$ vertx run server.js
listening on
8080
front
-router
rm1
rm2
front
-router

Help? This is functionality needed to authenticate unauthenticated users before letting them further into the system. If auth fails here, we kick them back out to sign-in.

Tim Fox

unread,
Jul 4, 2013, 4:17:22 AM7/4/13
to ve...@googlegroups.com
Please use gist.github.com for code snippets - trying to read it
completely unformatted in an email is giving me a headache ;)

Brad Orego

unread,
Jul 15, 2013, 4:27:22 PM7/15/13
to ve...@googlegroups.com
Ah, sorry about that. I'm reading it on the Google Groups page and it's still formatted nicely.

Tim Fox

unread,
Jul 15, 2013, 4:38:48 PM7/15/13
to ve...@googlegroups.com
Can you add a github issue? (In mod-lang-rhino project)

Brad Orego

unread,
Oct 1, 2013, 6:34:12 PM10/1/13
to ve...@googlegroups.com
I apparently never created an issue on Github for this, and now I see there's both a mod-lang-js and mod-lang-rhino repo on Github. Can someone point me toward the most up-to-date codebase so I can verify if this is still an issue? And/or someone with the most recent stuff built, could you test the above gist and see if it still hangs before the bodyHandler?

Brad Orego

unread,
Oct 2, 2013, 11:09:09 AM10/2/13
to ve...@googlegroups.com
Nevermind - built from source yesterday and the issue still exists. Github issue here: https://github.com/vert-x/mod-lang-rhino/issues/18. Let me know if there's any way I can help figure this one out :)
Reply all
Reply to author
Forward
0 new messages