Skip to content

Instantly share code, notes, and snippets.

@dougwilson
Last active October 12, 2020 19:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dougwilson/16d44df4036f19a2c0b1 to your computer and use it in GitHub Desktop.
Save dougwilson/16d44df4036f19a2c0b1 to your computer and use it in GitHub Desktop.
var express = require('express')
module.exports = createApplication
function createApplication() {
var app = express()
app._phases = Object.create(null)
app._mainline = null
app.phase = getPhase
app.lazyrouter = createLazyRouter(app, [
addPhase.call(app, 'init'),
addPhase.call(app, 'session'),
addPhase.call(app, 'auth'),
addPhase.call(app, 'log')
])
return app
}
function addPhase(name) {
var router = express.Router()
return this._phases[name] = router
}
function attachMainlineHandle(router, mainline) {
var _handle = router.handle
router.handle = mainline
return function handle(req, res, done) {
_handle.call(router, req, res, done)
}
}
function createLazyRouter(app, preroutes) {
var _init = app.lazyrouter
return function lazyrouter() {
if (!this._router) {
_init.call(this)
this._mainline = express.Router()
this._phases.routes = this._router
for (var i = 0; i < preroutes.length; i++) {
this._mainline.use(preroutes[i])
}
this._mainline.use(attachMainlineHandle(this._router, this._mainline))
this._mainline.use(addPhase.call(this, 'static'))
this._mainline.use(generateErrorPhase(addPhase.call(this, 'error')))
}
}
}
function generateErrorPhase(router) {
router.use(function raiseError(req, res, next) {
var err = req.__err
req.__err = undefined
next(err)
})
return function errorPhase(err, req, res, next) {
req.__err = err
router(req, res, next)
}
}
function getPhase(name) {
this.lazyrouter()
var router = this._phases[name]
if (!router) {
throw new TypeError('unknown phase "' + name + '"')
}
return router
}
var request = require('supertest')
var phasedApp = require('./phased_app')
var app = phasedApp()
app.phase('error').use(function (err, req, res, next) {
console.log('caught error: ' + err.message)
next()
})
app.phase('static').use(function (req, res, next) {
console.log('in static phase')
throw new Error('error in static')
})
app.use(function (req, res, next) {
console.log('in the routes phase')
next()
})
app.phase('auth').use(function (req, res, next) {
console.log('in the auth phase')
next()
})
request(app)
.get('/')
.expect(404, function (err) {
if (err) throw err
process.exit()
})
in the auth phase
in the routes phase
in static phase
caught error: error in static
@bajtos
Copy link

bajtos commented Nov 7, 2014

_handle.call(router, req, res, done)

I want to avoid call and apply in my solution, as they incur significant performance penalty.

A better solution:

function attachMainlineHandle(router, mainline) {
  router.__handle = router.handle
  router.handle = mainline

  return function handle(req, res, done) {
    router.__handle(req, res, done)
  }
}

@dougwilson
Copy link
Author

That's fine :) I usually end up using .call a lot these days to avoid introducing "magic" properties that people will see as a just in case. In fact, that makes me wonder what the benchmark of the following would be:

function attachMainlineHandle(router, mainline) {
  Object.defineProperty(router, '__handle', {
    configurable: false, 
    enumerable: false,
    value: router.handle
  })
  router.handle = mainline

  return function handle(req, res, done) {
    router.__handle(req, res, done)
  }
}

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