{"id":18317936,"url":"https://github.com/idiocc/goa-router","last_synced_at":"2025-04-09T13:51:34.848Z","repository":{"id":57113705,"uuid":"227707005","full_name":"idiocc/goa-router","owner":"idiocc","description":"The Router For Creating Middleware For Goa Apps.","archived":false,"fork":false,"pushed_at":"2019-12-21T08:52:08.000Z","size":314,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-15T07:48:59.252Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.idio.cc","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idiocc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-12T22:19:17.000Z","updated_at":"2019-12-21T08:52:11.000Z","dependencies_parsed_at":"2022-08-22T05:31:11.666Z","dependency_job_id":null,"html_url":"https://github.com/idiocc/goa-router","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":"mnpjs/package","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgoa-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgoa-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgoa-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fgoa-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idiocc","download_url":"https://codeload.github.com/idiocc/goa-router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054218,"owners_count":21039951,"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":[],"created_at":"2024-11-05T18:07:56.536Z","updated_at":"2025-04-09T13:51:34.829Z","avatar_url":"https://github.com/idiocc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @goa/router\n\n[![npm version](https://badge.fury.io/js/%40goa%2Frouter.svg)](https://www.npmjs.com/package/@goa/router)\n\n`@goa/router` is The Router For Creating Middleware For Goa Apps.\n\n```sh\nyarn add @goa/router\n```\n\n## Table Of Contents\n\n- [Table Of Contents](#table-of-contents)\n- [API](#api)\n  * [`Router`](#type-router)\n  * [\u003ccode\u003eRouterConfig\u003c/code\u003e](#type-routerconfig)\n- [Verbs](#verbs)\n- [Allowed Methods](#allowed-methods)\n  * [`AllowedMethodsOptions`](#type-allowedmethodsoptions)\n- [Named Routes](#named-routes)\n- [Multiple Middleware](#multiple-middleware)\n- [Nested Routes](#nested-routes)\n- [Router Prefixes](#router-prefixes)\n- [URL Parameters](#url-parameters)\n- [Copyright \u0026 License](#copyright--license)\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/0.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## API\n\nThe package is available by importing its default class:\n\n```js\nimport Router from '@goa/router'\n```\n\nThe example below creates a really simple router that responds to the `GET /` and `POST /users/:uid` requests. Because of `allowedMethods`, it will also send a response to the `OPTIONS` request with the `allow` header.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/index.js\"\u003eExample\u003c/a\u003e\u003c/th\u003e\u003cth\u003eOutput\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nimport rqt, { aqt } from 'rqt'\nimport Goa from '@goa/koa'\nimport Router from '@goa/router'\n\nconst goa = new Goa()\nconst router = new Router()\nrouter\n  .get('/', (ctx) =\u003e {\n    ctx.body = `Hello world`\n  })\n  .post('/users/:uid', (ctx) =\u003e {\n    ctx.body = `You have edited the user ${ctx.params.uid}`\n  })\ngoa.use(router.routes())\n\ngoa.use(router.allowedMethods())\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```sh\n​\n\n\n\n\n\n\n# GET /\nHello world\n\n# POST /users/100\nYou have edited the user 100\n\n\n# OPTIONS /\nHEAD, GET\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n\n__\u003ca name=\"type-router\"\u003e`Router`\u003c/a\u003e__: Router For Goa Apps.\n\u003ctable\u003e\n \u003cthead\u003e\u003ctr\u003e\n  \u003cth\u003eName\u003c/th\u003e\n  \u003cth\u003eType \u0026amp; Description\u003c/th\u003e\n \u003c/tr\u003e\u003c/thead\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003econstructor\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003enew (opts?: \u003ca href=\"#type-routerconfig\" title=\"Config for the router.\"\u003e!RouterConfig\u003c/a\u003e) =\u003e \u003ca href=\"#type-router\" title=\"Router For Goa Apps.\"\u003eRouter\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nCreate a new router.\n```js\nimport Goa from '＠goa/koa'\nimport Router from '＠goa/router'\n\nconst app = new Goa()\nconst router = new Router()\n\nrouter.get('/', (ctx, next) =\u003e {\n  // ctx.router available\n})\n\napp\n  .use(router.routes())\n  .use(router.allowedMethods())\n```\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003ckbd\u003estatic\u003c/kbd\u003e \u003cins\u003eurl\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(path: string, ...params: !Object[]) =\u003e string\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nGenerate URL from url pattern and given `params`.\n```js\nconst url = Router.url('/users/:id', { id: 1 })\n// =\u003e \"/users/1\"\n```\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eopts\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e\u003ca href=\"#type-routerconfig\" title=\"Config for the router.\"\u003e!RouterConfig\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Stored options passed to the \u003cem\u003eRouter\u003c/em\u003e constructor.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eallowedMethods\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(options: \u003ca href=\"#type-allowedmethodsoptions\" title=\"The options for the `allowedMethods` middleware generation.\"\u003e!AllowedMethodsOptions\u003c/a\u003e) =\u003e \u003ca href=\"https://github.com/idiocc/goa/wiki/Application#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nReturns separate middleware for responding to `OPTIONS` requests with\nan `Allow` header containing the allowed methods, as well as responding\nwith `405 Method Not Allowed` and `501 Not Implemented` as appropriate.\n```js\nimport Goa from '＠goa/koa'\nimport Router from '＠goa/router'\n\nconst app = new Goa()\nconst router = new Router()\n\napp.use(router.routes())\napp.use(router.allowedMethods())\n```\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eparam\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(param: string, middleware: \u003ca href=\"https://github.com/idiocc/goa/wiki/Application#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e) =\u003e \u003ca href=\"#type-router\" title=\"Router For Goa Apps.\"\u003e!Router\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nRun middleware for named route parameters. Useful for auto-loading or validation.\n```js\nrouter\n  .param('user', (id, ctx, next) =\u003e {\n    ctx.user = users[id]\n    if (!ctx.user) return ctx.status = 404\n    return next()\n  })\n  .get('/users/:user', ctx =\u003e {\n    ctx.body = ctx.user\n  })\n  .get('/users/:user/friends', async ctx =\u003e {\n    ctx.body = await ctx.user.getFriends()\n  })\n```\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eredirect\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(source: string, destination: string, code?: number) =\u003e \u003ca href=\"#type-router\" title=\"Router For Goa Apps.\"\u003e!Router\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Redirect \u003ccode\u003esource\u003c/code\u003e to \u003ccode\u003edestination\u003c/code\u003e URL with optional 30x status \u003ccode\u003ecode\u003c/code\u003e.\n   Both \u003ccode\u003esource\u003c/code\u003e and \u003ccode\u003edestination\u003c/code\u003e can be route names.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eroute\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(name: string) =\u003e Layer\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Lookup route with given \u003ccode\u003ename\u003c/code\u003e. If the route is not found, returns \u003ccode\u003enull\u003c/code\u003e.\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eurl\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(name: string, ...params: !Object[]) =\u003e (string | !Error)\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nGenerate URL for route. Takes a route name and map of named `params`. If the route is not found, returns an error. The last argument can be an object with the `query` property.\n```js\n// To use urls, a named route should be created:\nrouter.get('user', '/users/:id', (ctx, next) =\u003e {\n  // ...\n})\n```\nGet the URL by passing a **simple** parameter\n```js\nrouter.url('user', 3)\n// =\u003e \"/users/3\"\n```\nGet the URL by passing parameters in an **object**\n```js\nrouter.url('user', { id: 3 })\n// =\u003e \"/users/3\"\n```\nUse the url method for **redirects** to named routes:\n```js\nrouter.use((ctx) =\u003e {\n  ctx.redirect(ctx.router.url('sign-in'))\n})\n```\nPass an **object query**:\n```js\nrouter.url('user', { id: 3 }, { query: { limit: 1 } })\n// =\u003e \"/users/3?limit=1\"\n```\nPass an already **serialised query**:\n```js\nrouter.url('user', { id: 3 }, { query: 'limit=1' })\n// =\u003e \"/users/3?limit=1\"\n```\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003euse\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(path: (string | !Array\u0026lt;string\u0026gt; | \u003ca href=\"https://github.com/idiocc/goa/wiki/Application#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e), ...middleware: \u003ca href=\"https://github.com/idiocc/goa/wiki/Application#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e[]) =\u003e \u003ca href=\"#type-router\" title=\"Router For Goa Apps.\"\u003e!Router\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nUse given middleware.\nMiddleware run in the order they are defined by `.use()`. They are invoked\nsequentially, requests start at the first middleware and work their way\n\"down\" the middleware stack.\n```js\n// session middleware will run before authorize\nrouter\n  .use(session())\n  .use(authorize())\n// use middleware only with given path\nrouter.use('/users', userAuth())\n// or with an array of paths\nrouter.use(['/users', '/admin'], userAuth())\napp.use(router.routes())\n```\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003eprefix\u003c/ins\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e(prefix: string) =\u003e \u003ca href=\"#type-router\" title=\"Router For Goa Apps.\"\u003e!Router\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n\nSet the path prefix for a Router instance that was already initialized.\n```js\nrouter.prefix('/things/:thing_id')\n```\n  \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd rowSpan=\"3\" align=\"center\"\u003e\u003cins\u003emiddleware\u003c/ins\u003e\u003cbr\u003e\u003cins\u003eroutes\u003c/ins\u003e\u003csup\u003e\u003cem\u003ealias\u003c/em\u003e\u003c/sup\u003e\u003c/td\u003e\n  \u003ctd\u003e\u003cem\u003e() =\u003e \u003ca href=\"https://github.com/idiocc/goa/wiki/Application#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e\u003c/em\u003e\u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003c/tr\u003e\n \u003ctr\u003e\n  \u003ctd\u003e\n   Returns router middleware which dispatches a route matching the request.\n  \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cdetails\u003e\n \u003csummary\u003e\u003cstrong\u003e\u003ca name=\"type-routerconfig\"\u003e\u003ccode\u003eRouterConfig\u003c/code\u003e\u003c/a\u003e\u003c/strong\u003e: Config for the router.\u003c/summary\u003e\n\n|    Name    |             Type              |                                          Description                                          |\n| ---------- | ----------------------------- | --------------------------------------------------------------------------------------------- |\n| methods    | \u003cem\u003e!Array\u0026lt;string\u0026gt;\u003c/em\u003e | The methods to serve.\u003cbr/\u003eDefault `HEAD`, `OPTIONS`, `GET`, `PUT`, `PATCH`, `POST`, `DELETE`. |\n| prefix     | \u003cem\u003estring\u003c/em\u003e               | Prefix router paths.                                                                          |\n| routerPath | \u003cem\u003estring\u003c/em\u003e               | Custom routing path.                                                                          |\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/2.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Verbs\n\nRoutes are assigned to the router by calling HTTP method verbs on the instance:\n\n```js\nrouter\n  .get('/', (ctx, next) =\u003e {\n    ctx.body = 'Hello World!'\n  })\n  .post('/users', (ctx, next) =\u003e {\n    // ...\n  })\n  .put('/users/:id', (ctx, next) =\u003e {\n    // ...\n  })\n  .del('/users/:id', (ctx, next) =\u003e {\n    // ...\n  })\n  .all('/users/:id', (ctx, next) =\u003e {\n    // ...\n  })\n```\n\nAdditionally, `router.all()` can be used to match against all methods. `router.del()` is an alias for `router.delete()`.\n\nWhen a route is matched, its path is available at `ctx._matchedRoute` and if named, the name is available at `ctx._matchedRouteName`.\n\nRoute paths will be translated to regular expressions using [path-to-regexp](https://github.com/pillarjs/path-to-regexp).\n\nQuery strings will not be considered when matching requests.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/3.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Allowed Methods\n\nThe router can respond to the `OPTIONS` request with the `allow` header.\n\n**Example with [Boom](https://github.com/hapijs/boom)**\n\n```js\nconst app = new Goa()\nconst router = new Router()\n\napp.use(router.routes())\napp.use(router.allowedMethods({\n  throw: true,\n  notImplemented: () =\u003e new Boom.notImplemented(),\n  methodNotAllowed: () =\u003e new Boom.methodNotAllowed(),\n}))\n```\n\n__\u003ca name=\"type-allowedmethodsoptions\"\u003e`AllowedMethodsOptions`\u003c/a\u003e__: The options for the `allowedMethods` middleware generation.\n\n\n|       Name       |         Type          |                                Description                                 |\n| ---------------- | --------------------- | -------------------------------------------------------------------------- |\n| throw            | \u003cem\u003eboolean\u003c/em\u003e      | Throw error instead of setting status and header.                          |\n| notImplemented   | \u003cem\u003e() =\u003e !Error\u003c/em\u003e | Throw the returned value in place of the default `NotImplemented` error.   |\n| methodNotAllowed | \u003cem\u003e() =\u003e !Error\u003c/em\u003e | Throw the returned value in place of the default `MethodNotAllowed` error. |\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/4.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Named Routes\n\nRoutes can optionally have names. This allows generation of URLs and easy renaming of URLs during development.\n\n```js\nrouter.get('user', '/users/:id', (ctx, next) =\u003e {\n  // ...\n})\n\nrouter.url('user', 3)\n// =\u003e \"/users/3\"\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/5.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Multiple Middleware\n\nMultiple middleware may be passed to the router.\n\n```js\nrouter.get(\n  '/users/:id',\n  async (ctx, next) =\u003e {\n    const user = await User.findOne(ctx.params.id)\n    ctx.user = user\n    await next()\n  },\n  ctx =\u003e {\n    console.log(ctx.user)\n    // =\u003e { id: 17, name: \"Alex\" }\n  }\n)\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/6.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n\n## Nested Routes\n\nIt's possible to create a _Router_ instance, and then pass another _Router_ instance to its `.use` call to nest the two.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/nested.js\"\u003eSource\u003c/a\u003e\u003c/th\u003e\u003cth\u003eOutput\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nconst forums = new Router()\nconst posts = new Router()\n\nposts.get('/', (ctx) =\u003e {\n  ctx.body = ctx.params\n})\nposts.get('/:pid', (ctx) =\u003e {\n  ctx.body = ctx.params\n})\nforums.use('/forums/:fid/posts',\n  posts.routes(),\n  posts.allowedMethods())\n\ngoa.use(forums.routes())\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```js\n​\n\n\n// GET /forums/123/posts\n{ fid: '123' }\n\n// GET /forums/123/posts/123\n{ fid: '123', pid: '123' }\n\n\n\n\n\n​\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/7.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Router Prefixes\n\nRoute paths can be prefixed at the router level.\n\n```js\nconst router = new Router({\n  prefix: '/users',\n})\n\nrouter.get('/', (ctx) =\u003e {\n  // responds to \"/users\"\n  ctx.body = ctx.params\n})\nrouter.get('/:id', (ctx) =\u003e {\n  // responds to \"/users/:id\"\n  ctx.body = ctx.params\n})\n\ngoa.use(router.routes())\n```\n```js\n// Request /users\n{}\n// Request /users/123\n{ id: '123' }\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/8.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## URL Parameters\n\nNamed route parameters are captured and added to `ctx.params`.\n\n```js\nconst router = new Router()\n\nrouter.get('/:category/:title', (ctx) =\u003e {\n  // the params are exposed to the context.\n  ctx.body = ctx.params\n})\n\ngoa.use(router.routes())\n```\n```js\n// Request /programming/how-to-node\n{ category: 'programming', title: 'how-to-node' }\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/9.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Copyright \u0026 License\n\nGNU Affero General Public License v3.0\n\n[Original Work](https://github.com/ZijianHe/koa-router) by Alexander C. Mingoia under MIT License found in [COPYING](https://github.com/ZijianHe/koa-router/blob/master/LICENSE).\n\nThere's also a fork in the [Koa org](https://github.com/koajs/router).\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/40834161?s=100\u0026amp;v=4\" alt=\"idiocc\"\u003e\u003c/td\u003e\n    \u003ctd\u003e© \u003ca href=\"https://www.idio.cc\"\u003eIdio\u003c/a\u003e 2019\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/-1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fgoa-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidiocc%2Fgoa-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fgoa-router/lists"}