X-Git-Url: https://git.cworth.org/git?p=obsolete%2Fnotmuch-web;a=blobdiff_plain;f=node_modules%2Fexpress%2Flib%2Frouter%2Findex.js;fp=node_modules%2Fexpress%2Flib%2Frouter%2Findex.js;h=5a80b5c6405f81cd7c6019039ab53786b99c3723;hp=0000000000000000000000000000000000000000;hb=410c776334299b52b7df74c53dafe761ad51cf0d;hpb=df790f70fe96623e5d2469daedaf7114bde13426 diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js new file mode 100644 index 0000000..5a80b5c --- /dev/null +++ b/node_modules/express/lib/router/index.js @@ -0,0 +1,329 @@ + +/*! + * Express - router + * Copyright(c) 2010 TJ Holowaychuk + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var utils = require('../utils') + , parse = require('url').parse + , _methods = require('./methods') + , Route = require('./route'); + +/** + * Expose router. + */ + +exports = module.exports = router; + +/** + * Expose methods. + */ + +exports.methods = _methods; + +/** + * Provides Sinatra-like routing capabilities. + * + * @param {Function} fn + * @return {Function} + * @api private + */ + +function router(fn, app){ + 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); + } + + if (!path) throw new Error(name + ' route requires a path'); + if (!fn) throw new Error(name + ' route ' + path + ' requires a callback'); + + var options = { sensitive: app.enabled('case sensitive routes') }; + var route = new Route(name, path, fn, options); + route.middleware = middleware; + localRoutes.push(route); + 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.callback.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, ret){ + var ret = ret || [] + , route; + + // method specific remove + if (method) { + method = method.toUpperCase(); + if (routes[method]) { + for (var i = 0; i < routes[method].length; ++i) { + route = routes[method][i]; + if (path == route.path) { + route.index = i; + routes[method].splice(i, 1); + ret.push(route); + --i; + } + } + } + // global remove + } else { + _methods.forEach(function(method){ + router.remove(path, method, ret); + }); + } + + return ret; + }; + + 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.path) { + route.index = i; + ret.push(route); + } + }); + } + // 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 + , route + , req; + + // method specific matches + if (method) { + method = method.toUpperCase(); + req = { url: url, method: method }; + while (route = match(req, routes, i)) { + i = req._route_index + 1; + route.index = i; + ret.push(route); + } + // 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.send(body, { Allow: 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].regexp.test(path)) return true; + } + }).map(function(method){ + return method.toUpperCase(); + }); +} + +/** + * 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; + + // pass HEAD to GET routes + if ('HEAD' == method) method = 'GET'; + + // routes for this method + if (routes = routes[method]) { + var url = parse(req.url) + , pathname = url.pathname; + + // matching routes + for (var len = routes.length; i < len; ++i) { + var route = routes[i] + , fn = route.callback + , path = route.regexp + , keys = route.keys; + + // match + if (captures = path.exec(pathname)) { + route.params = []; + for (var j = 1, l = captures.length; j < l; ++j) { + var key = keys[j-1], + val = 'string' == typeof captures[j] + ? decodeURIComponent(captures[j]) + : captures[j]; + if (key) { + route.params[key] = val; + } else { + route.params.push(val); + } + } + req._route_index = i; + return route; + } + } + } +}