K-Router

© Keith Cirkel

K-Router may be freely distributed under the MIT license.

For all details and documentation: http://github.com/keithamus/k-router

This is the spec documentation for K-Router, generated by Mocha. If you want to see more detailed documentation about K-Router, check out the index.html page

Router

is passed through to app.use, with config argument
app.use(router({ }));
exposes a `.route` property through exports, so it can be required in
app.use(router({ }));

        router.route
            .should.be.a('function');

        router.resource
            .should.be.a('function');
has an alias for `.route` as `.route.route`
app.use(router({ app: app }));

        router.route
            .should.be.a('function');

        router.route.route
            .should.equal(router.route);

.route

basic routing

allows binding of routes
router.route('/x/y/z', view, 'respond', 'GET');

                request(app).get('/x/y/z')
                    .expect(200)
                    .end(next);
allows lower case HTTP verbs
router.route('/x/y/z', view, 'respond', 'get');

                request(app).get('/x/y/z')
                    .expect(200)
                    .end(next);
only matches the path
router.route('/x/y/z', view, 'respond', 'get');

                request(app).get('/x/y/z?v=1&x=2')
                    .expect(200)
                    .end(next);
will throw an error when using an invalid HTTP verb
var fn;

(fn = function () { router.route('/x/y/z', view, 'respond', 'FOO'); })
    .should.throw('Invalid HTTP method: FOO');
accepts regular expressions as the route
router.route(/^\/x\/y\/z$/i, view, 'respond', 'GET');

                request(app).get('/x/y/z')
                    .expect(200)
                    .end(next);
passes req, res and next functions to the method
router.route('/x/y/z', view, 'respond', 'GET');

                view.respond = function (request, response, next) {

                    request
                        .should.be.an('object');

                    response
                        .should.be.an('object');

                    next
                        .should.be.a('function');

                    next();
                };

                request(app).get('/x/y/z')
                    .expect(404)
                    .end(next);
will default the HTTP verb to GET, if omitted
router.route('/x/y/z', view, 'respond');

                request(app).get('/x/y/z')
                    .expect(200)
                    .end(next);
is only bound to that exact route
app.use(connect.errorHandler());

                router.route('/x/y/z', view, 'respond', 'GET');

                request(app).get('/x/y/z/a')
                    .expect(404)
                    .end(next);
will 405 if given a different HTTP verb
router.route('/x/y/z', view, 'respond', 'PUT');
                app.use(connect.errorHandler());

                request(app).get('/x/y/z').expect(405).expect('Allow', 'PUT').end(next);
can be bound to multiple verbs, and only one verb's method will fire
router.route('/x/y/z', view, 'respondPut', 'PUT');
                router.route('/x/y/z', view, 'respondGet', 'GET');
                app.use(connect.errorHandler());

                view.respondPut = function (req, res) {
                    res.statusCode = 200;
                    res.end('Put');
                };

                view.respondGet = function (req, res) {
                    res.statusCode = 200;
                    res.end('Get');
                };

                request(app).get('/x/y/z').expect(200).expect('Get').end(function () {
                    request(app).put('/x/y/z').expect(200).expect('Put').end(next);
                });
can be bound to multiple verb, and requests to other verbs will 405 with correct Allow header
router.route('/x/y/z', view, 'respondPut', 'PUT');
                router.route('/x/y/z', view, 'respondGet', 'GET');
                app.use(connect.errorHandler());

                view.respondPut = function (req, res) {
                    res.statusCode = 200;
                    res.end('Put');
                };

                view.respondGet = function (req, res) {
                    res.statusCode = 200;
                    res.end('Get');
                };

                request(app).post('/x/y/z').expect(405).expect('Allow', 'GET, PUT').end(next);

case sensitivity

will be insensitive by default
router.route('/x/y/z', view, 'respond', 'GET');

                request(app).get('/x/Y/z')
                    .expect(200)
                    .end(next);
will be sensitive when configured with urlsCaseSensitive: true
app.use(router({ urlsCaseSensitive: true }));

                router.route('/x/y/z', view, 'respond', 'GET');

                request(app).get('/x/Y/z')
                    .expect(404)
                    .end(next);

trailing slashes

will be be allowed and matched by default
router.route('/x/y/z', view, 'respond', 'GET');

                request(app).get('/x/y/z/')
                    .expect(200)
                    .end(next);
will not be matched with when configured with urlsAllowTrailingSlashes: true is passed
app.use(router({ urlsAllowTrailingSlashes: true }));

                router.route('/x/y/z', view, 'respond', 'GET');

                request(app).get('/x/y/z/')
                    .expect(404)
                    .end(next);

with parameters

injects named parameters into req.params
router.route('/x/y/:name/:age', view, 'respond', 'GET');

                view.respond = passErrorToCallback(next, function (req, res) {
                    req.params
                        .should.be.an('array');

                    req.params.name
                        .should.equal('foo');

                    req.params.age
                        .should.equal('21');

                    res.end('');

                });

                request(app).get('/x/y/foo/21').end(next);
does not match URLs with incomplete parameter sets
router.route('/x/y/:name/:age', view, 'respond', 'GET');

                request(app).get('/x/y/foo').expect(404).end(next);
decodes URI encoded parameters
router.route('/x/y/:name', view, 'respond', 'GET');

                view.respond = passErrorToCallback(next, function (req, res) {
                    req.params
                        .should.be.an('array');

                    req.params.name
                        .should.equal('hey,foo=:D');

                    res.end('');

                });

                request(app).get('/x/y/hey%2Cfoo%3D%3AD').end(next);
injects non-named parameters into req.params as array values
router.route('/x/y/*', view, 'respond', 'GET');

                view.respond = passErrorToCallback(next, function (req, res) {

                    req.params
                        .should.be.an('array');

                    req.params
                        .should.deep.equal(['foo/bar/baz/']);

                    res.end('');

                });

                request(app).get('/x/y/foo/bar/baz/').end(next);
injects regex match groups into req.params with indexes
router.route(/^\/(\w)\/(\w)\/(\w)\/?$/, view, 'respond', 'GET');

                view.respond = passErrorToCallback(next, function (req, res) {

                    req.params
                        .should.be.an('array');

                    req.params
                        .should.deep.equal(['foo', 'bar', 'baz']);

                    res.end('');

                });

                request(app).get('/foo/bar/baz/').end(next);

with optional parameters

will route to urls with optional parameters being supplied
router.route('/x/y/:name/:other?', view, 'respond', 'GET');

                view.respond = passErrorToCallback(next, function (req, res) {

                    req.params
                        .should.be.an('array');

                    req.params.name
                        .should.equal('foo');

                    req.params.other
                        .should.equal('bar');

                    res.end('');

                });

                request(app).get('/x/y/foo/bar').end(next);
will route to urls without the optional parameters being supplied
router.route('/x/y/:name/:other?', view, 'respond', 'GET');

                view.respond = passErrorToCallback(next, function (req, res) {

                    req.params
                        .should.be.an('array');

                    req.params.name
                        .should.equal('foo');

                    should.not.exist(req.params.other);

                    res.end('');

                });

                request(app).get('/x/y/foo').end(next);

.resouces

binds a route of the URL as a GET to controller#list
request(app).get('/x/y/z').expect(200).expect('list').end(next);
binds a route of the URL + "/new" as a GET to controller#new
request(app).get('/x/y/z/new').expect(200).expect('new').end(next);
binds a route of the URL as a POST to controller#create
request(app).post('/x/y/z').expect(200).expect('create').end(next);
binds a route of the URL + an ID as a GET to controller#show
request(app).get('/x/y/z/foo').expect(200).expect('show:foo').end(next);
binds a route of the URL + an ID + "/edit" as a GET to controller#edit
request(app).get('/x/y/z/foo/edit').expect(200).expect('edit:foo').end(next);
binds a route of the URL + an ID as a PUT to controller#update
request(app).put('/x/y/z/foo').expect(200).expect('update:foo').end(next);
binds a route of the URL + an ID as a PATCH to controller#update
request(app).patch('/x/y/z/foo').expect(200).expect('update:foo').end(next);
binds a route of the URL + an ID as a DELETE to controller#destroy
request(app).del('/x/y/z/foo').expect(200).expect('destroy:foo').end(next);
returns a 405 for POSTing to the URL + "/new"
request(app).post('/x/y/z/new').expect(405).end(next);
returns a 405 for DELETEing to the URL + "/new"
request(app).post('/x/y/z/new').expect(405).end(next);
returns a 405 for PUTing to the URL
request(app).put('/x/y/z').expect(405).end(next);
returns a 405 for DELETEing to the URL
request(app).del('/x/y/z').expect(405).end(next);
returns a 405 for POSTing to the URL + ID
request(app).post('/x/y/z/foo').expect(405).end(next);
only binds routes if the function is present
delete view.destroy;
            router(); // Reconfigure and empty existing routes
            router.route.resources('/x/y/z', view);

            request(app).del('/x/y/z/foo').expect(405).end(next);
only binds routes if the function is present
delete view.edit;
            router(); // Reconfigure and empty existing routes
            router.route.resources('/x/y/z', view);

            request(app).del('/x/y/z/bar/edit/').expect(404).end(next);

.resouce

binds a route of the URL as a GET to controller#show
request(app).get('/x/y/z').expect(200).expect('show').end(next);
binds a route of the URL + "/new" as a GET to controller#new
request(app).get('/x/y/z/new').expect(200).expect('new').end(next);
binds a route of the URL as a POST to controller#create
request(app).post('/x/y/z').expect(200).expect('create').end(next);
binds a route of the URL + "/edit" as a GET to controller#edit
request(app).get('/x/y/z/edit').expect(200).expect('edit').end(next);
binds a route of the URL as a PUT to controller#update
request(app).put('/x/y/z').expect(200).expect('update').end(next);
binds a route of the URL as a DELETE to controller#destroy
request(app).del('/x/y/z').expect(200).expect('destroy').end(next);
returns a 404 for GETing to the URL + ID
request(app).get('/x/y/z/foo').expect(404).end(next);
returns a 404 for POSTing to the URL + ID
request(app).post('/x/y/z/foo').expect(404).end(next);
returns a 404 for PUTing to the URL + ID
request(app).put('/x/y/z/foo').expect(404).end(next);
returns a 404 for PATCHing to the URL + ID
request(app).patch('/x/y/z/foo').expect(404).end(next);
returns a 404 for DELETEing to the URL + ID
request(app).del('/x/y/z/foo').expect(404).end(next);
returns a 405 for POSTing to the URL + "/new"
request(app).post('/x/y/z/new').expect(405).end(next);
returns a 405 for DELETEing to the URL + "/new"
request(app).post('/x/y/z/new').expect(405).end(next);
h