{"id":13799633,"url":"https://github.com/xinpianchang/koa2-router","last_synced_at":"2025-04-12T01:22:07.398Z","repository":{"id":71648414,"uuid":"160775317","full_name":"xinpianchang/koa2-router","owner":"xinpianchang","description":"An express-liked router component for koa2","archived":false,"fork":false,"pushed_at":"2020-03-01T06:39:20.000Z","size":60,"stargazers_count":8,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-09T10:45:59.158Z","etag":null,"topics":["koa","koa2","koa2-router","koajs","nodejs","router"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xinpianchang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2018-12-07T05:28:51.000Z","updated_at":"2021-02-11T03:58:35.000Z","dependencies_parsed_at":"2023-03-13T20:19:54.464Z","dependency_job_id":null,"html_url":"https://github.com/xinpianchang/koa2-router","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xinpianchang%2Fkoa2-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xinpianchang%2Fkoa2-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xinpianchang%2Fkoa2-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xinpianchang%2Fkoa2-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xinpianchang","download_url":"https://codeload.github.com/xinpianchang/koa2-router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248062902,"owners_count":21041671,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["koa","koa2","koa2-router","koajs","nodejs","router"],"created_at":"2024-08-04T00:01:04.657Z","updated_at":"2025-04-12T01:22:07.375Z","avatar_url":"https://github.com/xinpianchang.png","language":"JavaScript","funding_links":[],"categories":["仓库"],"sub_categories":["中间件"],"readme":"# koa2-router\nAn express-liked router component for koa2\n\n  [![NPM Version][npm-image]][npm-url]\n\n## Features\n* Express-style routing using .use|.params|.all|.route|[method]\n* Arrayed path prefix\n* Multiple, nestable router stacks\n* 405 Method Not Allowed support\n* 501 Not Implemented support\n* Named router for debug\n* Bounded baseUrl|url|params|matched|responded upon app.context|request|response\n\n## Getting Started\nYou can follow the instructions below to setup a router component in koa@2 environment. \n\n### Prerequisties\n* node version \u003e 8.10\n* depends on *koa*@2.0\n\n### Installing\n* If you use npm to manage your dependencies, run\n```\nnpm install koa2-router\n```\n\n### Usage\n* Import component\n```javascript\nconst Router = require('koa2-router');\n```\n\n* Create a router\n```javascript\nconst router = new Router(opts);\n```\n\n* Mount a router to a koa application\n```javascript\nconst app = new Koa();\napp.use(router);\n```\n\n* Mount a router to another router\n```javascript\nconst router2 = new Router();\nrouter2.use(...);\nrouter.use('/users', router2);\n```\n\n* Use http method to handle request\n```javascript\nrouter2.get('/:userId', ctx =\u003e ctx.body = `hello user ${ctx.params.userId}`);\n```\n\n* Use params middleware like express\n```javascript\nconst router3 = Router();\nrouter3.params('userName', (ctx, next, userName, key) =\u003e (ctx[key] = userName, next()))\n  .get('/:userName', async ctx =\u003e ctx.body = await ctx.db.getStaffFromName(ctx.userName));\nrouter.use('/staff', router3);\n```\n\n* Use route to make a rest api\n```javascript\nconst route = router3.route('/:id');\nroute\n  .get(async ctx =\u003e ctx.body = await ctx.db.getStaffFromId(ctx.params.id));\n```\n\n* exit route or router without exception\n```javascript\nroute\n  .all(async (ctx, next) =\u003e {\n     if (ctx.authenticate.userId === ctx.params.id) return next();\n     else throw 'route'; // exit this route without any exception\n  })   \n  .put(async ctx =\u003e ctx.body = await ctx.db.updateStaff(ctx.params.id, ctx.request.body))\n  .del(async ctx =\u003e ctx.body = await ctx.db.deleteStaff(ctx.params.id));\n  \nroute3.use('/admin', (ctx, next) =\u003e {\n    if (ctx.authenticate.userRoles.includes('admin')) return next();\n    else throw 'router'; // exit this router3 without any exception\n  })\n  .post('/posts', async ctx =\u003e ctx.body = await ctx.db.createPost(ctx.request.body, ctx.authenticate.userId));\n```\n\n* implement Method Not Allowed and Not Implemented\n```javascript\nrouter.use('/api', router3, router3.allowMethods(opts))\n```\n\n`opts` the allowMethods options\n\n`opts.throw` [boolean] default false, set to true to throw errors\n\n`opts.methodNotAllowed` [function(ctx, methods)] set if throw a custom 405 error\n\n`opts.notImplemented` [function(ctx)] set if throw a custom 501 error\n\n## Nested Router Stacks\nIn this module, router is a specific **function** instance which can be constructed via `router = new Router(opts)` or `router = Router(opts)`, and can be directly used as a `Koa.Middleware` function - `app.use(router)`.\n\nWe create a router model called **Express Liked Router Model**. The router constructed via this mechanism, implements everything that `express.Router` also dose, like `Router.use()`, `Router[method|all]()` `Router.params()` `Router.route()`.\n\nBut there is an issue about that mode, how nested router stacks proceed for an asynchronized middleware system.\n\nNested routers are supported, but not behaves like in a single stack: enter -\u003e enter -\u003e enter \u003c-\u003e leave \u003c- leave \u003c- leave. Considering the entering and leaving order of the stack is relevant to the way they are mounted, we consulted and borrowed the algo from a Golang open source project [gobwas/glob][4]: within that a new `Group` midleware is introduced, and it can make a branching stack. So we borrowed this design and setup new rules in nested routers in order to constraint excuting stack orders:\n\n1. Middlewares using `.use()` in which path can just be `/` or `*`, insert `middlewares` to the original stack\n\u003e in `Router.use(middlewares)`,  `middlewares` are inserted into\n\u003e the parent's middlewares, thus when the last one invokes `next()`, it\n\u003e will continue `enter` the next one of the parent router, until all\n\u003e things done, then it will `leave` from the bottom to the top of the\n\u003e parent router's stack\n\n2. Middlewares using `[method]` `.all` `.route` or `.use(path)` makes a branching stack of route nested in the parent stack\n\u003e in this situation, middlewares are handled via a mounted path or route\n\u003e if the one is matched both in path \u0026 route, calling `next` in the\n\u003e last middlewares of the nested router will `leave` the mounted router\n\u003e stack from bottom to the top first, and then if nothing is responded\n\u003e before that, it enters the next middleware of the parent stack\n\nLet's see an example\n```javascript\nvar router = new Router('A')\nvar nested = new Router('B')\nrouter.use(async (ctx, next) =\u003e {\n  console.log('enter parent')\n  await next()\n  console.log('leave parent')\n})\n// use `.use so nested mw is bundled together with the parent`\nrouter.use('/stuff', nested)\nrouter.use(async (ctx, next) =\u003e {\n  console.log('prepare')\n  await next()\n  console.log('post')\n})\nrouter.use(ctx =\u003e {\n  console.log('output body')\n  ctx.body = 'success'\n})\n\nnested.use(async (ctx, next) =\u003e {\n  console.log('enter nested')\n  await next()\n  console.log('leave nested')\n})\n```\n\n**GET /stuff** and watch the console\n```bash\n\u003e enter parent\n\u003e enter nested\n\u003e leave nested\n\u003e prepare\n\u003e output body\n\u003e post\n\u003e leave parent\n\n\u003e HTTP/1.1 200 OK\n\u003e success\n```\n\nThe order of entering/leaving differs between router and nested router. Because we make a branching stack nested in the router by mounting it to a path `/stuff`, and it will leave the branching stack before go over the next. It is just like the `Group` in the project [gobwas/glob](4) powered by golang\n\n## Running tests\nYou should clone thie repository down to your file system, and execute\n```\nnpm run test\n```\n\n## API Documents\n### Context\n* ctx.baseUrl: string\n* ctx.url: string\n* ctx.params: any\n* ctx.matched: string[]\n* ctx.responded: boolean\n\n### Router\n* class Router(name: string | opts: any):Middleware\n* router.use([path: string | string[]], ...middlewares: Middleware):Router\n* router.route(path: string | string[]):Route\n* router.all([path: string | string[]], ...middlewares: Middleware):Router\n* router[method]([path: string | string[]], ...middlewares: Middleware):Router\n* router.params(name: string, callback: (ctx, next, value: string, name: string) =\u003e void):Router\n\n### Route\n* route.all([path: string | string[]], ...middlewares: Middleware):Router\n* route[method]([path: string | string[]], ...middlewares: Middleware):Router\n\n## Acknowledgements\n* Thanks to the [expressjs/express][1] project\n* Thanks to the [alexmingoia/koa-router][2] project\n* Thanks to the [pillarjs/router][3] project\n* Thanks to the [gobwas/glob](4) project\n\n## License\n  [MIT](LICENSE)\n\n[npm-image]: https://img.shields.io/npm/v/koa2-router.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/koa2-router\n[1]: https://github.com/expressjs/express\n[2]: https://github.com/alexmingoia/koa-router\n[3]: https://github.com/pillarjs/router\n[4]: https://github.com/gobwas/glob\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxinpianchang%2Fkoa2-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxinpianchang%2Fkoa2-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxinpianchang%2Fkoa2-router/lists"}