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

Commit

Permalink
update with route-trie that support suffix matching
Browse files Browse the repository at this point in the history
  • Loading branch information
zensh committed Mar 24, 2017
1 parent b9ea58e commit 86c2749
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ node_js:
- "4"
- "6"
- "7"
cache:
directories:
- node_modules
script: "npm run test-cov"
after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls"
75 changes: 50 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
toa-router
====
# toa-router

A trie router for toa.

[![NPM version][npm-image]][npm-url]
Expand All @@ -14,16 +14,18 @@ A trie router for toa.
## Features

1. Support regexp
2. Support multi-router
3. Support router layer middlewares
4. Support fixed path automatic redirection
5. Support trailing slash automatic redirection
6. Automatic handle `405 Method Not Allowed`
7. Automatic handle `501 Not Implemented`
8. Automatic handle `OPTIONS` method
9. Best Performance
1. Support multi-router
1. Support suffix matching (package trie)
1. Support router layer middlewares
1. Support fixed path automatic redirection
1. Support trailing slash automatic redirection
1. Automatic handle `405 Method Not Allowed`
1. Automatic handle `501 Not Implemented`
1. Automatic handle `OPTIONS` method
1. Best Performance

## Demo

```js
const Toa = require('toa')
const Router = require('toa-router')
Expand Down Expand Up @@ -70,13 +72,15 @@ npm install toa-router

For pattern definitions, see [route-trie](https://github.com/zensh/route-trie).

The defined pattern can contain three types of parameters:
The defined pattern can contain six types of parameters:

| Syntax | Description |
|--------|------|
| `:name` | named parameter |
| `:name*` | named with catch-all parameter |
| `:name(regexp)` | named with regexp parameter |
| `:name+suffix` | named parameter with suffix matching |
| `:name(regexp)+suffix` | named with regexp parameter and suffix matching |
| `:name*` | named with catch-all parameter |
| `::name` | not named parameter, it is literal `:name` |

Named parameters are dynamic path segments. They match anything until the next '/' or the path end:
Expand All @@ -88,29 +92,47 @@ Defined: `/api/:type/:ID`
/api/user/123/comments no match
```

Named with catch-all parameters match anything until the path end, including the directory index (the '/' before the catch-all). Since they match anything until the end, catch-all parameters must always be the final path element.

Defined: `/files/:filepath*`
```
/files no match
/files/LICENSE matched: filepath="LICENSE"
/files/templates/article.html matched: filepath="templates/article.html"
```

Named with regexp parameters match anything using regexp until the next '/' or the path end:

Defined: `/api/:type/:ID(^\\d+$)`
Defined: `/api/:type/:ID(^\d+$)`
```
/api/user/123 matched: type="user", ID="123"
/api/user no match
/api/user/abc no match
/api/user/123/comments no match
```

The value of parameters is saved on the `context.params`. Retrieve the value of a parameter by name:
Named parameters with suffix, such as [Google API Design](https://cloud.google.com/apis/design/custom_methods):

Defined: `/api/:resource/:ID+:undelete`
```
let type = this.params.type
let id = this.params.ID
/api/file/123 no match
/api/file/123:undelete matched: resource="file", ID="123"
/api/file/123:undelete/comments no match
```

Named with regexp parameters and suffix:

Defined: `/api/:resource/:ID(^\d+$)+:cancel`
```
/api/task/123 no match
/api/task/123:cancel matched: resource="task", ID="123"
/api/task/abc:cancel no match
```

Named with catch-all parameters match anything until the path end, including the directory index (the '/' before the catch-all). Since they match anything until the end, catch-all parameters must always be the final path element.

Defined: `/files/:filepath*`
```
/files no match
/files/LICENSE matched: filepath="LICENSE"
/files/templates/article.html matched: filepath="templates/article.html"
```

The value of parameters is saved on the `matched.params`. Retrieve the value of a parameter by name:
```
type := matched.params("type")
id := matched.params("ID")
```

**Notice for regex pattern** from [route-trie](https://github.com/zensh/route-trie):
Expand Down Expand Up @@ -182,6 +204,7 @@ router.define('/:type/:id')
### And all `http.METHODS`

Support generator handler and async/await handler:

```js
router
.get('/:type/:id', function * () {
Expand All @@ -193,6 +216,7 @@ router
```

Support one more handlers:

```js
router
.get('/:type/:id', handler1, handler2, handler3)
Expand Down Expand Up @@ -233,6 +257,7 @@ router
### Router.prototype.toThunk()

Return a thunk function that wrap the router. We can use this thunk function as middleware.

```js
const app = Toa()
app.use(router.toThunk())
Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"authors": [
"Yan Qing <admin@zensh.com>"
],
"version": "2.0.1",
"version": "2.1.0",
"main": "index.js",
"repository": {
"type": "git",
"url": "git@github.com:toajs/toa-router.git"
},
"engines": {
"node": ">=4"
"node": ">= 4.0.0"
},
"homepage": "https://github.com/toajs/toa-router",
"keywords": [
Expand All @@ -23,15 +23,15 @@
"trie-router"
],
"dependencies": {
"route-trie": "^2.0.2",
"thunks": "^4.7.5"
"route-trie": "^2.1.0",
"thunks": "^4.7.6"
},
"devDependencies": {
"istanbul": "^0.4.5",
"standard": "^8.6.0",
"supertest": "^2.0.1",
"tman": "^1.6.4",
"toa": "^2.4.2"
"standard": "^9.0.2",
"supertest": "^3.0.0",
"tman": "^1.6.6",
"toa": "^2.6.2"
},
"scripts": {
"test": "standard && tman",
Expand Down
4 changes: 2 additions & 2 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function newApp (router) {
}

tman.suite('toa-router', function () {
tman.it('router.use, router.Handle', function * () {
tman.it('router.use, router.handle', function * () {
let called = 0
let router = new Router('/api')
let thunkObj = {
Expand All @@ -38,7 +38,7 @@ tman.suite('toa-router', function () {
let server = newApp(router)
yield request(server)
.get('/')
.expect(404)
.expect(421)
assert.strictEqual(called, 0)

yield request(server)
Expand Down

0 comments on commit 86c2749

Please sign in to comment.