Permalink
Browse files

does anyone really user after filters?

  • Loading branch information...
1 parent a35cfea commit d49943a31973443c867e9baedcaf50b1e8cf3e34 @dantebronto committed Jan 27, 2011
Showing with 122 additions and 19 deletions.
  1. +41 −2 examples/filters/app.js
  2. +12 −0 lib/picard/filters.js
  3. +17 −0 lib/picard/request.js
  4. +30 −17 lib/picard/routing.js
  5. +22 −0 spec/filters/filters_spec.js
@@ -35,13 +35,52 @@ Picard.routeSet('selective', function(){
})
this.get('/snappy_path', function(env){
- env.onScreen('Hello from the snappy path!') // After an async filter you'll need
- }) // to call onScreen in your route handler
+ env.onScreen('Hello from the snappy path!')
+ })
this.get('/login', function(){
return '<a href="/snappy_path?session_id=' + new Date().getTime() + '">fake login</a>'
})
})
+Picard.routeSet('afters', function(){
+
+ this.after(function(env){ // matches /.*/
+ // do stuff
+ return true // pass to the next after filter
+ })
+
+ this.after('fake', function(env){ // only matches routes with fake
+ // do other stuff
+ // return or not, doesn't matter at this point
+ })
+
+ this.get('/fake_path', function(env){
+ return 'Hello from the fake path!'
+ })
+
+ ////
+
+ this.after('foo', function(env){
+ env.foo = 'bar!'
+ env.filterDone()
+ })
+
+ this.after('foo', function(env){
+ process.nextTick(function(){
+ env.filterDone() // next after filter
+ })
+ })
+
+ this.after(function(env){
+ require('sys').puts(env.foo) // "bar!"
+ })
+
+ this.get('/foo_path', function(env){
+ return 'Hello from the foo path!'
+ })
+
+})
+
Picard.start()
View
@@ -10,6 +10,18 @@ var Filter = {
matcher: new RegExp(matcher), handler: cb
})
return this
+ },
+ after: function(matcher, cb){
+ if ( toString.call(matcher) == '[object Function]' ){
+ cb = matcher
+ matcher = '.*'
+ }
+ if ( !('afters' in this) ) this.afters = []
+
+ this.afters.push({
+ matcher: new RegExp(matcher), handler: cb
+ })
+ return this
}
}
View
@@ -192,6 +192,23 @@ var RequestExtensions = {
} catch(ex) {
req.handleException(ex)
}
+ } else if (req.afterFilters && req.afterFilters.length > 0 ) {
+
+ filter = req.afterFilters.shift()
+
+ try {
+ res = filter.handler(req) // call the filter
+
+ if ( res === false ){
+ return // stop execution
+ } else if ( res != undefined ) { // not false or undefined, so keep going
+ req.filterDone()
+ }
+
+ } catch (ex) {
+ req.log('error encountered in after filter: ')
+ req.log(ex)
+ }
} else { // we're done filtering
req.afterMainHandler(req.route.handler(req))
View
@@ -21,50 +21,53 @@ var Routes = {
return routingAPI
},
- executeCallback: function(request, cb){
- var routesByType = Routes.byRestType(request),
+ executeCallback: function(req, cb){
+ var routesByType = Routes.byRestType(req),
route, matches, path
for(var i=0, l = routesByType.length; i < l; i++){
route = routesByType[i]
- path = request.parsedUrl().pathname
+ path = req.parsedUrl().pathname
matches = path.match(route.path)
if( matches ){ // incoming request matches route
- if ( request.route ){
- if ( request.route == route )
- request.route = null // match the next route
+ if ( req.route ){
+ if ( req.route == route )
+ req.route = null // match the next route
continue
}
- request.extractRouteParams(route, matches)
+ req.extractRouteParams(route, matches)
try {
- request.route = route
+ req.route = route
if ( route.routeSet ){
if ( route.routeSet.befores ){
- route.routeSet.setMatchingBeforeFiltersOn(request, path)
- request.afterMainHandler = cb
- request.filterDone()
+ req.afterMainHandler = cb
+ route.routeSet.setMatchingBeforeFiltersOn(req, path)
} else {
- cb(route.handler(request)) // default
+
+ if ( route.routeSet.afters )
+ route.routeSet.setMatchingAfterFiltersOn(req, path)
+
+ cb(route.handler(req))
}
} else {
- cb(route.handler(request)) // call programmer defined action
+ cb(route.handler(req)) // call programmer defined action
}
} catch(ex) {
- request.handleException(ex)
+ req.handleException(ex)
}
}
}
- if ( !request.route )
+ if ( !req.route )
cb('static')
},
- byRestType: function(request){
- switch( (request._method || request.method).toUpperCase() ) {
+ byRestType: function(req){
+ switch( (req._method || req.method).toUpperCase() ) {
case 'GET' : return Routes.getRoutes
case 'POST' : return Routes.postRoutes
case 'PUT' : return Routes.putRoutes
@@ -197,6 +200,16 @@ RouteSet.prototype = {
req.beforeFilters.push(this.befores[i])
}
}
+ req.filterDone()
+ },
+ setMatchingAfterFiltersOn: function(req, path){
+ req.afterFilters = []
+ for(var i=0, len = this.afters.length; i<len; i++){
+ if ( this.afters[i].matcher.test(path) ){
+ req.afterFilters.push(this.afters[i])
+ }
+ }
+ req.filterDone()
}
}
@@ -32,3 +32,25 @@ describe('advanced before filters', function(){
})
})
+
+describe('after filters', function(){
+
+ it('should allow after filters', function(){
+ testReq('GET', '/fake_path', function(status, _, body){
+ expect(status).toEqual(200)
+ expect(body).toMatch('fake path')
+ asyncSpecDone()
+ })
+ asyncSpecWait()
+ })
+
+ it('should honor onScreen calls from the before filters', function(){
+ testReq('GET', '/foo_path', function(status, _, body){
+ expect(status).toEqual(200)
+ expect(body).toMatch('foo path')
+ asyncSpecDone()
+ })
+ asyncSpecWait()
+ })
+
+})

0 comments on commit d49943a

Please sign in to comment.