From 1d2955a800f5ff0830788fe9345db6d2ee1acb84 Mon Sep 17 00:00:00 2001 From: "Fangdun Cai (Fundon)" Date: Tue, 2 Aug 2016 04:36:00 +0800 Subject: [PATCH] improve --- index.js | 41 ++++++++++++++++++----------------------- test/node.js | 5 +++-- test/rest.test.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 test/rest.test.js diff --git a/index.js b/index.js index 88cc729..262c88a 100644 --- a/index.js +++ b/index.js @@ -34,12 +34,11 @@ const COLON = 58 // ':' */ class Node { - constructor (prefix = '/', children, handlers, pnames) { + constructor (prefix = '/', children, maps) { this.label = prefix.charCodeAt(0) this.prefix = prefix this.children = children || [] - this.handlers = handlers || Object.create(null) - this.pnames = pnames + this.maps = maps || Object.create(null) } /** @@ -60,12 +59,12 @@ class Node { return } - addHandler (method, handler) { - this.handlers[method] = handler + addMap (method, map) { + this.maps[method] = map } - findHandler (method) { - return this.handlers[method] + findMap (method) { + return this.maps[method] } } @@ -162,29 +161,25 @@ class Router { cn.label = search.charCodeAt(0) cn.prefix = search if (handler !== undefined) { - cn.pnames = pnames - cn.addHandler(method, handler) + cn.addMap(method, { pnames, handler }) } } else if (l < pl) { // Split node - n = new Node(cn.prefix.substring(l), cn.children, cn.handlers, cn.pnames) + n = new Node(cn.prefix.substring(l), cn.children, cn.maps) cn.children = [n] // Add to parent // Reset parent node cn.label = cn.prefix.charCodeAt(0) cn.prefix = cn.prefix.substring(0, l) - cn.handler = undefined - cn.pnames = undefined - cn.handlers = Object.create(null) + cn.maps = Object.create(null) if (l === sl) { // At parent node - cn.pnames = pnames - cn.addHandler(method, handler) + cn.addMap(method, { pnames, handler }) } else { // Create child node - n = new Node(search.substring(l), [], Object.create(null), pnames) - n.addHandler(method, handler) + n = new Node(search.substring(l), []) + n.addMap(method, { pnames, handler }) cn.children.push(n) } } else if (l < sl) { @@ -196,14 +191,13 @@ class Router { continue } // Create child node - n = new Node(search, [], Object.create(null), pnames) - n.addHandler(method, handler) + n = new Node(search, []) + n.addMap(method, { pnames, handler }) cn.children.push(n) } else { // Node already exists if (handler !== undefined) { - cn.pnames = pnames - cn.addHandler(method, handler) + cn.addMap(method, { pnames, handler }) } } return @@ -232,8 +226,9 @@ class Router { // Search order static > param > match-any if (search.length === 0 || search === cn.prefix) { // Found - if ((result[0] = cn.findHandler(method)) !== undefined) { - let pnames = cn.pnames + let map = cn.findMap(method) + if ((result[0] = map && map.handler) !== undefined) { + let pnames = map.pnames if (pnames !== undefined) { for (let i = 0, l = pnames.length; i < l; ++i) { params[i].name = pnames[i] diff --git a/test/node.js b/test/node.js index e9b2593..7e417db 100644 --- a/test/node.js +++ b/test/node.js @@ -5,13 +5,14 @@ function prefix(tail, p, on, off) { return format('%s%s', p, tail ? on : off) } -Node.prototype.printTree = function printTree(pfx, tail) { +Node.prototype.printTree = function printTree(pfx, tail, method = 'GET') { + let map = this.maps[method] let p = prefix(tail, pfx, '└── ', '├── ') console.log( '%s%s h=%s children=%s', p, this.prefix, - this.handler ? 'function' : undefined, + map && map.handler ? map.handler.name : '', this.children.length ) diff --git a/test/rest.test.js b/test/rest.test.js new file mode 100644 index 0000000..5335ed3 --- /dev/null +++ b/test/rest.test.js @@ -0,0 +1,44 @@ +import _ from 'lodash' +import assert from 'power-assert' +import Router from '..' +import './node' + +function createFunc(name) { + var a = `(function ${name||''}(){})` + return eval(a) +} + +// https://github.com/labstack/echo/issues/479 +const api = [ + ['GET', '/:piyo', '/piyo', 'piyo'], + ['POST', '/:hoge', '/hoge', 'hoge'], +] + +describe('Rest API', () => { + let r + + beforeEach(() => { + r = new Router() + _.shuffle(api).forEach((i) => { + let [method, path] = i + r.add(method, path, createFunc(_.camelCase('rest-api' + path + '-' + method))) + }) + }) + + it('Parse API routes', () => { + r.tree.printTree('', true, 'GET') + r.tree.printTree('', true, 'POST') + }) + + _.shuffle(api).forEach((i) => { + let [method, path, realpath, paramName] = i + it(path, () => { + let [handler, params] = r.find(method, realpath) + console.log(method, path, realpath, handler.name, params) + assert.notEqual(null, handler) + assert.equal(_.camelCase('rest-api' + path + '-' + method), handler.name) + assert.equal((path.match(/\:/g) || []).length, params.length) + assert.equal(params[0].name, paramName) + }) + }) +})