Skip to content
This repository has been archived by the owner on Aug 17, 2023. It is now read-only.

Commit

Permalink
support middleware in router.
Browse files Browse the repository at this point in the history
  • Loading branch information
zensh committed Aug 25, 2016
1 parent 3336f5f commit 0e5c90a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 16 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ A trie router for toa.
- `405 Method Not Allowed` support
- `501 Not Implemented` support
- `multi router` support with different url prefix
- `middleware` support middleware with different url prefix

## Demo
```js
Expand All @@ -26,6 +27,10 @@ var Router = require('toa-router')

var router = new Router()

router.use(function () {
console.log('Hello, middleware.')
})

router
.get('', function () {
// sync handle
Expand Down Expand Up @@ -165,6 +170,36 @@ router

Set default route definition that will be used when no other route definition is matched.

### Router.prototype.use(middleware)

Add middlewares to this router. They will run before router handle.

```js
router.use(function () {
console.log('sync middleware')
})

router.use(function () {
console.log('promise middleware')
return Promise.resolve('something')
})

router.use(function (done) {
console.log('sync middleware')
done()
})

router.use(function * () {
console.log('generator middleware')
yield 'something'
})

router.use(async function () {
console.log('async/await middleware')
await Promise.resolve('something')
})
```

### Pattern Definitions

For pattern definitions, see [route-trie](https://github.com/zensh/route-trie).
Expand Down
39 changes: 29 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
// **License:** MIT

var path = require('path')
var thunk = require('thunks')()
var thunks = require('thunks')
var methods = require('methods')
var Trie = require('route-trie')
var thunk = thunks()

module.exports = Router

function RouterState (root) {
this.root = typeof root === 'string' ? root.replace(/(\/)+$/, '') : ''
this.trie = new Trie()
this.preHooks = []
this.otherwise = null
}

Expand All @@ -32,8 +34,12 @@ Router.prototype.define = function (pattern) {
}

Router.prototype.otherwise = function (handler) {
if (typeof handler !== 'function') throw new TypeError('Handler must be a function.')
this._routerState.otherwise = handler
this._routerState.otherwise = toThunkableFn(handler)
return this
}

Router.prototype.use = function (fn) {
this._routerState.preHooks.push(toThunkableFn(fn))
return this
}

Expand All @@ -46,6 +52,12 @@ Router.prototype.toThunk = function () {

Router.prototype.route = function (context) {
var state = this._routerState
var otherwise = state.otherwise
var preHooks = this._routerState.preHooks.slice()

function worker (ctx, handler) {
return thunk.seq.call(ctx, preHooks)(function () { return handler })
}

return thunk.call(context, function (done) {
var normalPath = path.normalize(this.path).replace(/\\/g, '/')
Expand All @@ -57,7 +69,7 @@ Router.prototype.route = function (context) {

var matched = state.trie.match(normalPath)
if (!matched) {
if (state.otherwise) return thunk.call(this, state.otherwise.call(this))(done)
if (otherwise) return worker(this, otherwise)(done)
this.throw(501, '"' + this.path + '" is not implemented.')
}

Expand All @@ -76,13 +88,13 @@ Router.prototype.route = function (context) {
// If no route handler is returned
// it's a 405 error
if (!handler) {
if (state.otherwise) return thunk.call(this, state.otherwise.call(this))(done)
if (otherwise) return worker(this, otherwise)(done)
this.set('Allow', matched.node.allowMethods)
this.throw(405, this.method + ' is not allowed in "' + this.path + '".')
}

this.params = this.request.params = matched.params
return thunk.call(this, handler.call(this))(done)
worker(this, handler)(done)
})
}

Expand All @@ -97,12 +109,12 @@ function Route (router, pattern) {

methods.forEach(function (method) {
Router.prototype[method] = function (pattern, handler) {
defineHandler(this._routerState.trie.define(pattern), method, handler)
defineHandler(this._routerState.trie.define(pattern), method, toThunkableFn(handler))
return this
}

Route.prototype[method] = function (handler) {
defineHandler(this._node, method, handler)
defineHandler(this._node, method, toThunkableFn(handler))
return this
}
})
Expand All @@ -114,9 +126,16 @@ function defineHandler (node, method, handler) {
method = method.toUpperCase()
node.methods = node.methods || Object.create(null)

if (node.methods[method]) throw new Error('The route in "' + node._nodeState.pattern + '" already defined.')
if (typeof handler !== 'function') throw new TypeError('Handler must be a function.')
if (node.methods[method]) {
throw new Error('The route in "' + node._nodeState.pattern + '" already defined.')
}
node.methods[method] = handler
if (!node.allowMethods) node.allowMethods = method
else node.allowMethods += ', ' + method
}

function toThunkableFn (fn) {
if (typeof fn !== 'function') throw new TypeError('must be a function!')
if (thunks.isThunkableFn(fn)) return fn
return function (done) { thunk.call(this, fn.call(this))(done) }
}
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"authors": [
"Yan Qing <[email protected]>"
],
"version": "1.4.0",
"version": "1.5.0",
"main": "index.js",
"repository": {
"type": "git",
Expand All @@ -25,13 +25,13 @@
"dependencies": {
"methods": "^1.1.2",
"route-trie": "^1.2.6",
"thunks": "^4.4.2"
"thunks": "^4.5.0"
},
"devDependencies": {
"standard": "^7.1.2",
"standard": "^8.0.0",
"supertest": "^2.0.0",
"tman": "^1.0.4",
"toa": "^1.8.2"
"tman": "^1.1.0",
"toa": "^1.8.7"
},
"scripts": {
"test": "standard && tman"
Expand Down
30 changes: 29 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict'
/*global Promise*/
/* global Promise */

var assert = require('assert')
var request = require('supertest')
Expand Down Expand Up @@ -259,4 +259,32 @@ tman.suite('toa-router', function () {
.expect(200)
.expect('api')
})

tman.it('middleware', function () {
var count = 0
var router = new Router()

router.use(function () {
count++
})

router.use(function (done) {
setTimeout(function () {
count++
done()
}, 100)
})

router.get('', function () {
this.body = String(count)
})

var app = toa()
app.use(router.toThunk())

return request(app.listen())
.get('/')
.expect(200)
.expect('2')
})
})

0 comments on commit 0e5c90a

Please sign in to comment.