Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Removed `router()` middleware. Closes #262

  • Loading branch information...
commit 2ca7ec3ff64cb7600bfd029233228236bf048671 1 parent 7d96c75
@tj tj authored
Showing with 0 additions and 802 deletions.
  1. +0 −379 lib/middleware/router.js
  2. +0 −423 test/router.test.js
View
379 lib/middleware/router.js
@@ -1,379 +0,0 @@
-
-/*!
- * Connect - router
- * Copyright(c) 2010 Sencha Inc.
- * Copyright(c) 2011 TJ Holowaychuk
- * MIT Licensed
- */
-
-/**
- * Module dependencies.
- */
-
-var utils = require('../utils')
- , parse = require('url').parse;
-
-/**
- * Expose router.
- */
-
-exports = module.exports = router;
-
-/**
- * Supported HTTP / WebDAV methods.
- */
-
-var _methods = exports.methods = [
- 'get'
- , 'post'
- , 'put'
- , 'delete'
- , 'connect'
- , 'options'
- , 'trace'
- , 'copy'
- , 'lock'
- , 'mkcol'
- , 'move'
- , 'propfind'
- , 'proppatch'
- , 'unlock'
- , 'report'
- , 'mkactivity'
- , 'checkout'
- , 'merge'
-];
-
-/**
- * Provides Sinatra and Express-like routing capabilities.
- *
- * Examples:
- *
- * connect.router(function(app){
- * app.get('/user/:id', function(req, res, next){
- * // populates req.params.id
- * });
- * app.put('/user/:id', function(req, res, next){
- * // populates req.params.id
- * });
- * })
- *
- * @param {Function} fn
- * @return {Function}
- * @api public
- */
-
-function router(fn){
- var self = this
- , methods = {}
- , routes = {}
- , params = {};
-
- if (!fn) throw new Error('router provider requires a callback function');
-
- // Generate method functions
- _methods.forEach(function(method){
- methods[method] = generateMethodFunction(method.toUpperCase());
- });
-
- // Alias del -> delete
- methods.del = methods.delete;
-
- // Apply callback to all methods
- methods.all = function(){
- var args = arguments;
- _methods.forEach(function(name){
- methods[name].apply(this, args);
- });
- return self;
- };
-
- // Register param callback
- methods.param = function(name, fn){
- params[name] = fn;
- };
-
- fn.call(this, methods);
-
- function generateMethodFunction(name) {
- var localRoutes = routes[name] = routes[name] || [];
- return function(path, fn){
- var keys = []
- , middleware = [];
-
- // slice middleware
- if (arguments.length > 2) {
- middleware = Array.prototype.slice.call(arguments, 1, arguments.length);
- fn = middleware.pop();
- middleware = utils.flatten(middleware);
- }
-
- fn.middleware = middleware;
-
- if (!path) throw new Error(name + ' route requires a path');
- if (!fn) throw new Error(name + ' route ' + path + ' requires a callback');
- var regexp = path instanceof RegExp
- ? path
- : normalizePath(path, keys);
- localRoutes.push({
- fn: fn
- , path: regexp
- , keys: keys
- , orig: path
- , method: name
- });
- return self;
- };
- }
-
- function router(req, res, next){
- var route
- , self = this;
-
- (function pass(i){
- if (route = match(req, routes, i)) {
- var i = 0
- , keys = route.keys;
-
- req.params = route.params;
-
- // Param preconditions
- (function param(err) {
- try {
- var key = keys[i++]
- , val = req.params[key]
- , fn = params[key];
-
- if ('route' == err) {
- pass(req._route_index + 1);
- // Error
- } else if (err) {
- next(err);
- // Param has callback
- } else if (fn) {
- // Return style
- if (1 == fn.length) {
- req.params[key] = fn(val);
- param();
- // Middleware style
- } else {
- fn(req, res, param, val);
- }
- // Finished processing params
- } else if (!key) {
- // route middleware
- i = 0;
- (function nextMiddleware(err){
- var fn = route.middleware[i++];
- if ('route' == err) {
- pass(req._route_index + 1);
- } else if (err) {
- next(err);
- } else if (fn) {
- fn(req, res, nextMiddleware);
- } else {
- route.call(self, req, res, function(err){
- if (err) {
- next(err);
- } else {
- pass(req._route_index + 1);
- }
- });
- }
- })();
- // More params
- } else {
- param();
- }
- } catch (err) {
- next(err);
- }
- })();
- } else if ('OPTIONS' == req.method) {
- options(req, res, routes);
- } else {
- next();
- }
- })();
- };
-
- router.remove = function(path, method){
- var fns = router.lookup(path, method);
- fns.forEach(function(fn){
- routes[fn.method].splice(fn.index, 1);
- });
- };
-
- router.lookup = function(path, method, ret){
- ret = ret || [];
-
- // method specific lookup
- if (method) {
- method = method.toUpperCase();
- if (routes[method]) {
- routes[method].forEach(function(route, i){
- if (path == route.orig) {
- var fn = route.fn;
- fn.regexp = route.path;
- fn.keys = route.keys;
- fn.path = route.orig;
- fn.method = route.method;
- fn.index = i;
- ret.push(fn);
- }
- });
- }
- // global lookup
- } else {
- _methods.forEach(function(method){
- router.lookup(path, method, ret);
- });
- }
-
- return ret;
- };
-
- router.match = function(url, method, ret){
- var ret = ret || []
- , i = 0
- , fn
- , req;
-
- // method specific matches
- if (method) {
- method = method.toUpperCase();
- req = { url: url, method: method };
- while (fn = match(req, routes, i)) {
- i = req._route_index + 1;
- ret.push(fn);
- }
- // global matches
- } else {
- _methods.forEach(function(method){
- router.match(url, method, ret);
- });
- }
-
- return ret;
- };
-
- return router;
-}
-
-/**
- * Respond to OPTIONS.
- *
- * @param {ServerRequest} req
- * @param {ServerResponse} req
- * @param {Array} routes
- * @api private
- */
-
-function options(req, res, routes) {
- var pathname = parse(req.url).pathname
- , body = optionsFor(pathname, routes).join(',');
- res.writeHead(200, {
- 'Content-Length': body.length
- , 'Allow': body
- });
- res.end(body);
-}
-
-/**
- * Return OPTIONS array for the given `path`, matching `routes`.
- *
- * @param {String} path
- * @param {Array} routes
- * @return {Array}
- * @api private
- */
-
-function optionsFor(path, routes) {
- return _methods.filter(function(method){
- var arr = routes[method.toUpperCase()];
- for (var i = 0, len = arr.length; i < len; ++i) {
- if (arr[i].path.test(path)) return true;
- }
- }).map(function(method){
- return method.toUpperCase();
- });
-}
-
-/**
- * Normalize the given path string,
- * returning a regular expression.
- *
- * An empty array should be passed,
- * which will contain the placeholder
- * key names. For example "/user/:id" will
- * then contain ["id"].
- *
- * @param {String} path
- * @param {Array} keys
- * @return {RegExp}
- * @api private
- */
-
-function normalizePath(path, keys) {
- path = path
- .concat('/?')
- .replace(/\/\(/g, '(?:/')
- .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
- keys.push(key);
- slash = slash || '';
- return ''
- + (optional ? '' : slash)
- + '(?:'
- + (optional ? slash : '')
- + (format || '') + (capture || '([^/]+?)') + ')'
- + (optional || '');
- })
- .replace(/([\/.])/g, '\\$1')
- .replace(/\*/g, '(.+)');
- return new RegExp('^' + path + '$', 'i');
-}
-
-/**
- * Attempt to match the given request to
- * one of the routes. When successful
- * a route function is returned.
- *
- * @param {ServerRequest} req
- * @param {Object} routes
- * @return {Function}
- * @api private
- */
-
-function match(req, routes, i) {
- var captures
- , method = req.method
- , i = i || 0;
- if ('HEAD' == method) method = 'GET';
- if (routes = routes[method]) {
- var url = parse(req.url)
- , pathname = url.pathname;
- for (var len = routes.length; i < len; ++i) {
- var route = routes[i]
- , fn = route.fn
- , path = route.path
- , keys = fn.keys = route.keys;
- if (captures = path.exec(pathname)) {
- fn.method = method;
- fn.params = [];
- for (var j = 1, len = captures.length; j < len; ++j) {
- var key = keys[j-1],
- val = typeof captures[j] === 'string'
- ? decodeURIComponent(captures[j])
- : captures[j];
- if (key) {
- fn.params[key] = val;
- } else {
- fn.params.push(val);
- }
- }
- req._route_index = i;
- return fn;
- }
- }
- }
-}
View
423 test/router.test.js
@@ -1,423 +0,0 @@
-
-/**
- * Module dependencies.
- */
-
-var connect = require('connect')
- , assert = require('assert')
- , should = require('should')
- , http = require('http')
- , create = require('./common').create;
-
-module.exports = {
- 'test methods': function(){
- var app = create(
- connect.router(function(app){
- app.get('/', function(req, res){
- res.end('GET /');
- });
-
- app.post('/', function(req, res){
- res.end('POST /');
- });
-
- app.put('/', function(req, res){
- res.end('PUT /');
- });
- })
- );
-
- assert.response(app,
- { url: '/' },
- { body: 'GET /' });
-
- assert.response(app,
- { url: '/', method: 'POST' },
- { body: 'POST /' });
-
- assert.response(app,
- { url: '/', method: 'PUT' },
- { body: 'PUT /' });
- },
-
- 'test params': function(){
- var app = create(
- connect.router(function(app){
- app.get('/user/:id', function(req, res){
- res.end('user ' + req.params.id);
- });
-
- app.get('/user/:id/:op', function(req, res){
- res.end(req.params.op + 'ing user ' + req.params.id);
- });
- })
- );
-
- assert.response(app,
- { url: '/user/12/' },
- { body: 'user 12' });
-
- assert.response(app,
- { url: '/user/12' },
- { body: 'user 12' });
-
- assert.response(app,
- { url: '/user/tj.holowaychuk' },
- { body: 'user tj.holowaychuk' });
-
- assert.response(app,
- { url: '/user/12/edit' },
- { body: 'editing user 12' });
- },
-
- 'test optional params': function(){
- var app = create(
- connect.router(function(app){
- app.get('/user/:id?', function(req, res){
- res.end('user ' + (req.params.id || 'account'));
- });
-
- app.get('/account/:id?/:op', function(req, res){
- res.end(req.params.op + 'ing user ' + (req.params.id || 'account'));
- });
- })
- );
-
- assert.response(app,
- { url: '/user/12' },
- { body: 'user 12' });
-
- assert.response(app,
- { url: '/account/edit' },
- { body: 'editing user account' });
-
- assert.response(app,
- { url: '/account/12/edit' },
- { body: 'editing user 12' });
- },
-
- 'test splat': function(){
- var app = create(
- connect.router(function(app){
- app.get('/file/*', function(req, res){
- res.end('file ' + req.params[0]);
- });
- })
- );
-
- assert.response(app,
- { url: '/file' },
- { status: 404 });
-
- assert.response(app,
- { url: '/file/jquery.js' },
- { body: 'file jquery.js' });
-
- assert.response(app,
- { url: '/file/public/javascripts/jquery.js' },
- { body: 'file public/javascripts/jquery.js' });
- },
-
- 'test several splats': function(){
- var app = create(
- connect.router(function(app){
- app.get('/file/*.*', function(req, res){
- res.end('file ' + req.params[0] + ' ext ' + req.params[1]);
- });
-
- app.get('/move/*/to/*', function(req, res){
- res.end('moved ' + req.params[0] + ' to ' + req.params[1]);
- });
- })
- );
-
- assert.response(app,
- { url: '/file/jquery.js' },
- { body: 'file jquery ext js' });
-
- assert.response(app,
- { url: '/file/public/javascripts/jquery.js' },
- { body: 'file public/javascripts/jquery ext js' });
-
- assert.response(app,
- { url: '/move/jquery/to/jquery.js' },
- { body: 'moved jquery to jquery.js' });
- },
-
- 'test named captures': function(){
- var app = create(
- connect.router(function(app){
- app.get('/page/:from(\\d+)-:to(\\d+)', function(req, res){
- res.end('viewing ' + req.params.from + ' to ' + req.params.to);
- });
- })
- );
-
- assert.response(app,
- { url: '/page/1-9' },
- { body: 'viewing 1 to 9' });
-
- assert.response(app,
- { url: '/page/3-b' },
- { status: 404 });
- },
-
- 'test format': function(){
- var app = create(
- connect.router(function(app){
- app.get('/users.:format', function(req, res){
- res.end('format ' + req.params.format);
- });
-
- app.get('/users', function(req, res){
- res.end('users');
- });
- })
- );
-
- assert.response(app,
- { url: '/users' },
- { body: 'users' });
-
- assert.response(app,
- { url: '/users.json' },
- { body: 'format json' });
- },
-
- 'test optional format': function(){
- var app = create(
- connect.router(function(app){
- app.get('/users.:format?', function(req, res){
- res.end('format ' + (req.params.format || 'html'));
- });
- })
- );
-
- assert.response(app,
- { url: '/users' },
- { body: 'format html' });
-
- assert.response(app,
- { url: '/users.json' },
- { body: 'format json' });
- },
-
- 'test regular expressions': function(){
- var app = create(
- connect.router(function(app){
- app.get(/\/commits\/(\w+)\.\.(\w+)\/?/i, function(req, res){
- res.end(
- 'from ' + req.params[0]
- + ' to ' + req.params[1]);
- });
- })
- );
-
- assert.response(app,
- { url: '/commits/abc..def' },
- { body: 'from abc to def' });
- },
-
- 'test next()': function(){
- var hits = [];
-
- var app = create(
- connect.router(function(app){
- app.get('/:user', function(req, res, next){
- hits.push('a');
- next();
- });
-
- app.get('/:user', function(req, res, next){
- hits.push('b');
- next();
- });
-
- app.get('/:user', function(req, res, next){
- hits.push('c');
- res.end(req.params.user);
- });
- })
- );
-
- assert.response(app,
- { url: '/tj' },
- { body: 'tj' },
- function(){
- hits.should.eql(['a', 'b', 'c']);
- });
- },
-
- 'test next(err)': function(){
- var hits = [];
-
- var app = create(
- connect.router(function(app){
- app.get('/:user', function(req, res, next){
- hits.push('a');
- next();
- });
-
- app.get('/:user', function(req, res, next){
- hits.push('b');
- next(new Error('keyboard cat'));
- });
-
- app.get('/:user', function(req, res, next){
- hits.push('c');
- res.end(req.params.user);
- });
- }),
- function(err, req, res, next) {
- res.end(err.toString());
- }
- );
-
- assert.response(app,
- { url: '/tj' },
- { body: 'Error: keyboard cat' },
- function(){
- hits.should.eql(['a', 'b']);
- });
- },
-
- 'test HEAD': function(){
- var app = create(
- connect.router(function(app){
- app.get('/items', function(req, res){
- res.end('HEAD' == req.method
- ? ''
- : 'foo, bar, baz');
- });
- })
- );
-
- assert.response(app,
- { url: '/items', method: 'HEAD' },
- { body: '' });
- },
-
- 'test OPTIONS': function(){
- var app = create(
- connect.router(function(app){
- app.get('/items', function(){});
- app.post('/items', function(){});
- app.get('/users', function(){});
- app.options('/accounts', function(req, res){
- res.writeHead(204, { Allow: 'GET' });
- res.end();
- });
- })
- );
-
- assert.response(app,
- { url: '/items', method: 'OPTIONS' },
- { body: 'GET,POST', headers: { Allow: 'GET,POST' }});
-
- assert.response(app,
- { url: '/users', method: 'OPTIONS' },
- { body: 'GET', headers: { Allow: 'GET' }});
-
- assert.response(app,
- { url: '/accounts', method: 'OPTIONS' },
- { headers: { Allow: 'GET' }});
- },
-
- 'test immutable params': function(){
- var app = create(
- connect.router(function(app){
- app.get('/user/:id', function(req, res, next){
- req.params.id = parseInt(req.params.id, 10);
- next();
- });
-
- app.get('/user/:id', function(req, res){
- res.end(typeof req.params.id);
- });
- })
- );
-
- assert.response(app,
- { url: '/user/12' },
- { body: 'string' });
- },
-
- 'test .lookup()': function(){
- var router = connect.router(function(app){
- app.get('/user/:id', function(req, res, next){
- req.params.id = parseInt(req.params.id, 10);
- next();
- });
-
- app.get('/user/:id', function(req, res){
- res.end(typeof req.params.id);
- });
-
- app.put('/user/:id', function(){});
- app.get('/user/:id/edit', function(){});
- app.post('/user', function(){});
- });
-
- var fn = router.lookup('/user/:id')[0];
- fn.regexp.should.be.an.instanceof(RegExp);
- fn.path.should.equal('/user/:id');
- fn.method.should.equal('GET');
- fn.keys.should.eql(['id']);
-
- router.lookup('/user/:id')[0].should.be.a('function');
- router.lookup('/user/:id').should.have.length(3);
- router.lookup('/user/:id', 'GET').should.have.length(2);
- router.lookup('/user/:id', 'get').should.have.length(2);
- router.lookup('/user/:id/edit', 'GET').should.have.length(1);
- router.lookup('/user/:id', 'PUT').should.have.length(1);
- router.lookup('/user/:id', 'FOO').should.be.empty;
- },
-
- 'test .match()': function(){
- var router = connect.router(function(app){
- app.get('/user/:id', function(req, res, next){
- req.params.id = parseInt(req.params.id, 10);
- next();
- });
-
- app.get('/user/:id', function(req, res){
- res.end(typeof req.params.id);
- });
-
- app.put('/user/:id', function(){});
- app.get('/user/:id/edit', function(){});
- app.post('/user', function(){});
- });
-
- var fn = router.match('/user/12')[0];
- fn.keys.should.eql(['id']);
- fn.params.id.should.equal('12');
-
- router.match('/').should.be.empty;
- router.match('/', 'GET').should.be.empty;
- router.match('/user/12', 'GET')[0].should.be.a('function');
- router.match('/user/12/edit', 'GET').should.have.length(1);
- router.match('/user/12', 'GET').should.have.length(2);
- router.match('/user/12', 'PUT').should.have.length(1);
- router.match('/user', 'POST').should.have.length(1);
- router.match('/user').should.have.length(1);
- },
-
- 'test .remove()': function(){
- var router = connect.router(function(app){
- app.get('/', function(req, res){});
- app.get('/foo/bar', function(req, res){});
- app.get('/bar', function(req, res){});
- app.put('/bar', function(req, res){});
- app.post('/bar', function(req, res){});
- });
-
- router.remove('/', 'GET');
- router.remove('/bar');
- router.lookup('/', 'GET').should.be.empty;
- router.lookup('/bar', 'GET').should.be.empty;
- router.lookup('/bar', 'PUT').should.be.empty;
- router.lookup('/bar', 'POST').should.be.empty;
- router.lookup('/foo/bar', 'GET').should.not.be.empty;
- }
-};
Please sign in to comment.
Something went wrong with that request. Please try again.