{"id":18337241,"url":"https://github.com/pillarjs/routington","last_synced_at":"2025-04-07T12:08:54.260Z","repository":{"id":8094551,"uuid":"9508944","full_name":"pillarjs/routington","owner":"pillarjs","description":"Trie-based URL Routing","archived":false,"fork":false,"pushed_at":"2014-12-27T22:11:18.000Z","size":418,"stargazers_count":185,"open_issues_count":6,"forks_count":23,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-05-08T16:53:24.133Z","etag":null,"topics":[],"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/pillarjs.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}},"created_at":"2013-04-17T22:32:55.000Z","updated_at":"2024-03-03T23:48:11.000Z","dependencies_parsed_at":"2022-09-13T14:21:47.858Z","dependency_job_id":null,"html_url":"https://github.com/pillarjs/routington","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pillarjs%2Froutington","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pillarjs%2Froutington/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pillarjs%2Froutington/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pillarjs%2Froutington/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pillarjs","download_url":"https://codeload.github.com/pillarjs/routington/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247648978,"owners_count":20972945,"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-05T20:10:34.090Z","updated_at":"2025-04-07T12:08:54.238Z","avatar_url":"https://github.com/pillarjs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Routington\n\n[![NPM version][npm-image]][npm-url]\n[![Build status][travis-image]][travis-url]\n[![Test coverage][coveralls-image]][coveralls-url]\n[![Dependency Status][david-image]][david-url]\n[![License][license-image]][license-url]\n[![Downloads][downloads-image]][downloads-url]\n[![Gittip][gittip-image]][gittip-url]\n\nRoutington is a [trie](http://en.wikipedia.org/wiki/Trie)-based URL router.\nIts goal is only to define and match URLs.\nIt does not handle methods, headers, controllers, views, etc., in anyway.\nIt is faster than traditional, linear, regular expression-matching routers, although insignficantly,\nand scales with the number of routes.\n\nThe purpose of this router isn't for performance,\nbut to bring more structure to URL routing.\nThe intention is for you to build a framework on top either in node.js or in the browser.\n\nImplementations:\n\n  - [koa-trie-router](https://github.com/koajs/trie-router) - for [koa](https://github.com/koajs)\n  - [wayfarer](https://github.com/yoshuawuyts/wayfarer)\n\n### API\n\n#### node Node = Routington()\n\n```js\nvar routington = require('routington')\nvar router = routington()\n```\n\n`router` is the root `Node` in the trie. All `node`s will have `router` as furthest ancestor.\n\n#### Node\n\nEvery node on a tree is an instance of `Node`. You only construct the root. A `node` has the following properties:\n\n- `child {}Node` - String based child definitions.\n  For example, `node.child['post']` will return a child node with `node.string === 'post'`\n- `children []Node` - Name/regex based child definitions\n- `parent Node` - The parent of the node\n- `name` - Name of the node (for parameter matching)\n- `string` - String to match the URL fragment\n- `regex` - Regular expression to match the URL fragment\n\n#### nodes []Node = router.define(route)\n\n```js\nvar nodes = router.define('/:identity(page|petition)/:id([0-9a-f]{24})')\n```\n\n- `route` is a definition of a route and is an extension of Express' routing syntax.\n  `route`, however, can only be a string.\n- `nodes` is an array of `node`s.\n\nEach fragment of the route, delimited by a `/`, can have the following signature:\n\n- `string` - ex `/post`\n- `string|string` - `|` separated strings, ex `/post|page`\n- `:name` - Wildcard route matched to a name\n- `(regex)` - A regular expression match without saving the parameter (not recommended)\n- `:name(regex)`- Named regular expression match\n\nYou should always name your regular expressions otherwise you can't use the captured value.\nThe regular expression is built using `new RegExp('^(' + regex + ')$', 'i')`,\nso you need to escape your string, ie `\\\\w`.\nYou can always pre-define names or regular expressions before. For example, I can define:\n\n```js\nrouter.define('/page/:id(\\\\w{3,30})')\n\n// later, :id will have the same regexp\n// so you don't have to repeat yourself\nrouter.define('/page/:id/things')\n```\n\n#### match {} = router.match(url)\n\n```js\nrouter.define('/page/:id(\\\\w{3,30})')\nvar match = router.match('/page/taylorswift')\n```\n\n`match`, unless `null`, will be an object with the following properties:\n\n- `param` - A list of named parameters, ex, `match.param.id === 'taylorswift'`.\n- `node` - The matched node.\n  Will always have `name.string === ''`.\n\n### Building a Router on top of Routington\n\nEach URL you define creates a node,\nand you are free to do whatever you'd like with each node as long you don't overwrite any prototype properties (basically just `define`, `match`, and `parse`).\nAdding any features to routington shouldn't be necessary.\n\nFor example, suppose you want to attach callbacks to a node by extending routington:\n\n```js\nrouter.get('/:id/:controller', function (req, res, next) {\n  console.log('do something')\n})\n```\n\nYou can attach the middleware to a `node.GET` array:\n\n```js\nrouter.get = function (path, handler) {\n  var node = router.define(path)[0]\n  node.GET = node.GET || []\n  node.GET.push(handler)\n}\n```\n\nNow, dispatching is easy:\n\n```js\nfunction dispatcher(req, res, next) {\n  var match = router.match(url.parse(req.url).pathname)\n  if (!match)\n    // this is a 404\n\n  var node = match.node\n  var callbacks = node[req.method]\n  if (!callbacks)\n    // this is a 405\n\n  // execute all the callbacks.\n  // async.series won't actually work here,\n  // but you get the point.\n  async.series(callbacks, next)\n}\n```\n\nProperties attached to the node will be exposed on the match.\nFor example,\nsuppose you wanted to label a node:\n\n```js\nvar node = router.define('/:id/:controller')[0]\nnode.label = 'controller'\n```\n\nWhen matched, it will be available via `match.node.label`:\n\n```js\nvar match = router.match('/someid/somecontroller')\nassert(match.node.label === 'label')\n```\n\nSince reaching into `match.node` is a little inconvenient and you probably don't want your end users to touch it,\nyou should expose in your dispatcher:\n\n```js\nvar match = router.match(url.parse(req.url).pathname)\n\n// ...\n\nreq.param = match.param\nreq.label = match.node.label\n```\n\n### Browser Support\n\nIE9+\n\n[npm-image]: https://img.shields.io/npm/v/routington.svg?style=flat-square\n[npm-url]: https://npmjs.org/package/routington\n[github-tag]: http://img.shields.io/github/tag/pillarjs/routington.svg?style=flat-square\n[github-url]: https://github.com/pillarjs/routington/tags\n[travis-image]: https://img.shields.io/travis/pillarjs/routington.svg?style=flat-square\n[travis-url]: https://travis-ci.org/pillarjs/routington\n[coveralls-image]: https://img.shields.io/coveralls/pillarjs/routington.svg?style=flat-square\n[coveralls-url]: https://coveralls.io/r/pillarjs/routington?branch=master\n[david-image]: http://img.shields.io/david/pillarjs/routington.svg?style=flat-square\n[david-url]: https://david-dm.org/pillarjs/routington\n[license-image]: http://img.shields.io/npm/l/routington.svg?style=flat-square\n[license-url]: LICENSE.md\n[downloads-image]: http://img.shields.io/npm/dm/routington.svg?style=flat-square\n[downloads-url]: https://npmjs.org/package/routington\n[gittip-image]: https://img.shields.io/gittip/jonathanong.svg?style=flat-square\n[gittip-url]: https://www.gittip.com/jonathanong/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpillarjs%2Froutington","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpillarjs%2Froutington","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpillarjs%2Froutington/lists"}