Skip to content

Commit

Permalink
Add Router events
Browse files Browse the repository at this point in the history
The following events were added:

1. `handlestart` - emitted when the router starts to handle the
router stack.
2. `layer` - emitted when a layer is macthed by the router. It
returns the matched layer.
3. `handleend` - emitted when the router has completed handling
the router stack.

I am sure very sure about the name of the events, feedback are
most welcome.
  • Loading branch information
hacksparrow committed Oct 27, 2016
1 parent d3a598d commit 40c292f
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
15 changes: 15 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ var mixin = require('utils-merge')
var parseUrl = require('parseurl')
var Route = require('./lib/route')
var setPrototypeOf = require('setprototypeof')
var EventEmitter = require('events').EventEmitter
var routerEvents = ['handlestart', 'layer', 'handleend']

/**
* Module variables.
Expand Down Expand Up @@ -64,6 +66,9 @@ function Router(options) {
router.handle(req, res, next)
}

// make Router an EventEmitter
mixin(this, EventEmitter.prototype, false)

// inherit from the correct prototype
setPrototypeOf(router, this)

Expand Down Expand Up @@ -164,6 +169,7 @@ Router.prototype.handle = function handle(req, res, callback) {
var self = this
var slashAdded = false
var paramcalled = {}
var events = self._events

// middleware and routes
var stack = this.stack
Expand All @@ -186,6 +192,9 @@ Router.prototype.handle = function handle(req, res, callback) {
req.baseUrl = parentUrl
req.originalUrl = req.originalUrl || req.url

// trigger the "beginning of route handling" event
if (events && routerEvents[0] in events) self.emit('handlestart', req)

next()

function next(err) {
Expand Down Expand Up @@ -269,6 +278,9 @@ Router.prototype.handle = function handle(req, res, callback) {
return done(layerError)
}

// trigger the "layer found" event
if (events && routerEvents[1] in events) self.emit(routerEvents[1], layer, req)

// store route for dispatch on change
if (route) {
req.route = route
Expand All @@ -280,6 +292,9 @@ Router.prototype.handle = function handle(req, res, callback) {
: layer.params
var layerPath = layer.path

// trigger the "end of route handling" event
if (events && routerEvents[2] in events && idx === stack.length) self.emit(routerEvents[2], req)

// this should be done for the layer
self.process_params(layer, paramcalled, req, res, function (err) {
if (err) {
Expand Down
111 changes: 111 additions & 0 deletions test/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ var after = require('after')
var methods = require('methods')
var Router = require('..')
var utils = require('./support/utils')
var IncomingMessage = require('http').IncomingMessage
var Layer = require('../lib/layer.js')

var assert = utils.assert
var createHitHandle = utils.createHitHandle
Expand Down Expand Up @@ -983,8 +985,117 @@ describe('Router', function () {
.expect(200, 'saw GET /bar', done)
})
})

describe('events', function () {

describe('"handlestart"', function () {
it('should pass the request object', function (done) {
var router = new Router()
var server = createServer(router)

router.on('handlestart', function (req) {
assert(IncomingMessage.prototype.isPrototypeOf(req))
done()
})

request(server).get('/').end()
})

it('should be emitted at the beginning of handling the router stack', function (done) {
var router = new Router()
var server = createServer(router)

var handlers = [passThrough, passThrough, passThrough]
router.use(handlers)

var counter = 0
router.on('layer', function (layer, req) {
counter++
})
router.on('handlestart', function (req) {
assert.equal(0, counter)
done()
})

request(server).get('/').end()
})
})

describe('"layer"', function () {
it('should pass the matched layer and the request object', function (done) {
var router = new Router()
var server = createServer(router)

router.use(passThrough)

router.on('layer', function (layer, req) {
assert(Layer.prototype.isPrototypeOf(layer))
assert(IncomingMessage.prototype.isPrototypeOf(req))
done()
})

request(server).get('/').end()
})

it('should be emitted for each layer of the router stack', function (done) {
var router = new Router()
var server = createServer(router)

var handlers = [passThrough, passThrough, passThrough]
router.use(handlers)

var counter = 0
router.on('layer', function (layer, req) {
counter++
if (handlers.length === counter) done()
})

request(server).get('/').end()
})
})

describe('"handleend"', function () {
it('should pass the request object', function (done) {
var router = new Router()
var server = createServer(router)

router.use(passThrough)

router.on('handleend', function (req) {
assert(IncomingMessage.prototype.isPrototypeOf(req))
done()
})

request(server).get('/').end()
})

it('should be emitted at the end of handling the router stack', function (done) {
var router = new Router()
var server = createServer(router)

var handlers = [passThrough, passThrough, passThrough]
router.use(handlers)

var counter = 0
router.on('layer', function (layer, req) {
counter++
})
router.on('handleend', function (req) {
assert.equal(handlers.length, counter)
done()
})

request(server).get('/').end()
})
})

})
})

function passThrough(req, res, next) {
next()
}

function helloWorld(req, res) {
res.statusCode = 200
res.setHeader('Content-Type', 'text/plain')
Expand Down

0 comments on commit 40c292f

Please sign in to comment.