aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/express/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/express/lib')
-rw-r--r--node_modules/express/lib/application.js531
-rw-r--r--node_modules/express/lib/express.js92
-rw-r--r--node_modules/express/lib/middleware.js33
-rw-r--r--node_modules/express/lib/request.js526
-rw-r--r--node_modules/express/lib/response.js756
-rw-r--r--node_modules/express/lib/router/index.js273
-rw-r--r--node_modules/express/lib/router/route.js72
-rw-r--r--node_modules/express/lib/utils.js313
-rw-r--r--node_modules/express/lib/view.js76
9 files changed, 2672 insertions, 0 deletions
diff --git a/node_modules/express/lib/application.js b/node_modules/express/lib/application.js
new file mode 100644
index 0000000..e841c12
--- /dev/null
+++ b/node_modules/express/lib/application.js
@@ -0,0 +1,531 @@
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+ , Router = require('./router')
+ , methods = require('methods')
+ , middleware = require('./middleware')
+ , debug = require('debug')('express:application')
+ , locals = require('./utils').locals
+ , View = require('./view')
+ , utils = connect.utils
+ , path = require('path')
+ , http = require('http')
+ , join = path.join;
+
+/**
+ * Application prototype.
+ */
+
+var app = exports = module.exports = {};
+
+/**
+ * Initialize the server.
+ *
+ * - setup default configuration
+ * - setup default middleware
+ * - setup route reflection methods
+ *
+ * @api private
+ */
+
+app.init = function(){
+ this.cache = {};
+ this.settings = {};
+ this.engines = {};
+ this.defaultConfiguration();
+};
+
+/**
+ * Initialize application configuration.
+ *
+ * @api private
+ */
+
+app.defaultConfiguration = function(){
+ // default settings
+ this.enable('x-powered-by');
+ this.set('env', process.env.NODE_ENV || 'development');
+ this.set('subdomain offset', 2);
+ debug('booting in %s mode', this.get('env'));
+
+ // implicit middleware
+ this.use(connect.query());
+ this.use(middleware.init(this));
+
+ // inherit protos
+ this.on('mount', function(parent){
+ this.request.__proto__ = parent.request;
+ this.response.__proto__ = parent.response;
+ this.engines.__proto__ = parent.engines;
+ this.settings.__proto__ = parent.settings;
+ });
+
+ // router
+ this._router = new Router(this);
+ this.routes = this._router.map;
+ this.__defineGetter__('router', function(){
+ this._usedRouter = true;
+ this._router.caseSensitive = this.enabled('case sensitive routing');
+ this._router.strict = this.enabled('strict routing');
+ return this._router.middleware;
+ });
+
+ // setup locals
+ this.locals = locals(this);
+
+ // default locals
+ this.locals.settings = this.settings;
+
+ // default configuration
+ this.set('view', View);
+ this.set('views', process.cwd() + '/views');
+ this.set('jsonp callback name', 'callback');
+
+ this.configure('development', function(){
+ this.set('json spaces', 2);
+ });
+
+ this.configure('production', function(){
+ this.enable('view cache');
+ });
+};
+
+/**
+ * Proxy `connect#use()` to apply settings to
+ * mounted applications.
+ *
+ * @param {String|Function|Server} route
+ * @param {Function|Server} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.use = function(route, fn){
+ var app;
+
+ // default route to '/'
+ if ('string' != typeof route) fn = route, route = '/';
+
+ // express app
+ if (fn.handle && fn.set) app = fn;
+
+ // restore .app property on req and res
+ if (app) {
+ app.route = route;
+ fn = function(req, res, next) {
+ var orig = req.app;
+ app.handle(req, res, function(err){
+ req.app = res.app = orig;
+ req.__proto__ = orig.request;
+ res.__proto__ = orig.response;
+ next(err);
+ });
+ };
+ }
+
+ connect.proto.use.call(this, route, fn);
+
+ // mounted an app
+ if (app) {
+ app.parent = this;
+ app.emit('mount', this);
+ }
+
+ return this;
+};
+
+/**
+ * Register the given template engine callback `fn`
+ * as `ext`.
+ *
+ * By default will `require()` the engine based on the
+ * file extension. For example if you try to render
+ * a "foo.jade" file Express will invoke the following internally:
+ *
+ * app.engine('jade', require('jade').__express);
+ *
+ * For engines that do not provide `.__express` out of the box,
+ * or if you wish to "map" a different extension to the template engine
+ * you may use this method. For example mapping the EJS template engine to
+ * ".html" files:
+ *
+ * app.engine('html', require('ejs').renderFile);
+ *
+ * In this case EJS provides a `.renderFile()` method with
+ * the same signature that Express expects: `(path, options, callback)`,
+ * though note that it aliases this method as `ejs.__express` internally
+ * so if you're using ".ejs" extensions you dont need to do anything.
+ *
+ * Some template engines do not follow this convention, the
+ * [Consolidate.js](https://github.com/visionmedia/consolidate.js)
+ * library was created to map all of node's popular template
+ * engines to follow this convention, thus allowing them to
+ * work seamlessly within Express.
+ *
+ * @param {String} ext
+ * @param {Function} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.engine = function(ext, fn){
+ if ('function' != typeof fn) throw new Error('callback function required');
+ if ('.' != ext[0]) ext = '.' + ext;
+ this.engines[ext] = fn;
+ return this;
+};
+
+/**
+ * Map the given param placeholder `name`(s) to the given callback(s).
+ *
+ * Parameter mapping is used to provide pre-conditions to routes
+ * which use normalized placeholders. For example a _:user_id_ parameter
+ * could automatically load a user's information from the database without
+ * any additional code,
+ *
+ * The callback uses the samesignature as middleware, the only differencing
+ * being that the value of the placeholder is passed, in this case the _id_
+ * of the user. Once the `next()` function is invoked, just like middleware
+ * it will continue on to execute the route, or subsequent parameter functions.
+ *
+ * app.param('user_id', function(req, res, next, id){
+ * User.find(id, function(err, user){
+ * if (err) {
+ * next(err);
+ * } else if (user) {
+ * req.user = user;
+ * next();
+ * } else {
+ * next(new Error('failed to load user'));
+ * }
+ * });
+ * });
+ *
+ * @param {String|Array} name
+ * @param {Function} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.param = function(name, fn){
+ var self = this
+ , fns = [].slice.call(arguments, 1);
+
+ // array
+ if (Array.isArray(name)) {
+ name.forEach(function(name){
+ fns.forEach(function(fn){
+ self.param(name, fn);
+ });
+ });
+ // param logic
+ } else if ('function' == typeof name) {
+ this._router.param(name);
+ // single
+ } else {
+ if (':' == name[0]) name = name.substr(1);
+ fns.forEach(function(fn){
+ self._router.param(name, fn);
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Assign `setting` to `val`, or return `setting`'s value.
+ *
+ * app.set('foo', 'bar');
+ * app.get('foo');
+ * // => "bar"
+ *
+ * Mounted servers inherit their parent server's settings.
+ *
+ * @param {String} setting
+ * @param {String} val
+ * @return {Server} for chaining
+ * @api public
+ */
+
+app.set = function(setting, val){
+ if (1 == arguments.length) {
+ return this.settings[setting];
+ } else {
+ this.settings[setting] = val;
+ return this;
+ }
+};
+
+/**
+ * Return the app's absolute pathname
+ * based on the parent(s) that have
+ * mounted it.
+ *
+ * For example if the application was
+ * mounted as "/admin", which itself
+ * was mounted as "/blog" then the
+ * return value would be "/blog/admin".
+ *
+ * @return {String}
+ * @api private
+ */
+
+app.path = function(){
+ return this.parent
+ ? this.parent.path() + this.route
+ : '';
+};
+
+/**
+ * Check if `setting` is enabled (truthy).
+ *
+ * app.enabled('foo')
+ * // => false
+ *
+ * app.enable('foo')
+ * app.enabled('foo')
+ * // => true
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.enabled = function(setting){
+ return !!this.set(setting);
+};
+
+/**
+ * Check if `setting` is disabled.
+ *
+ * app.disabled('foo')
+ * // => true
+ *
+ * app.enable('foo')
+ * app.disabled('foo')
+ * // => false
+ *
+ * @param {String} setting
+ * @return {Boolean}
+ * @api public
+ */
+
+app.disabled = function(setting){
+ return !this.set(setting);
+};
+
+/**
+ * Enable `setting`.
+ *
+ * @param {String} setting
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.enable = function(setting){
+ return this.set(setting, true);
+};
+
+/**
+ * Disable `setting`.
+ *
+ * @param {String} setting
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.disable = function(setting){
+ return this.set(setting, false);
+};
+
+/**
+ * Configure callback for zero or more envs,
+ * when no `env` is specified that callback will
+ * be invoked for all environments. Any combination
+ * can be used multiple times, in any order desired.
+ *
+ * Examples:
+ *
+ * app.configure(function(){
+ * // executed for all envs
+ * });
+ *
+ * app.configure('stage', function(){
+ * // executed staging env
+ * });
+ *
+ * app.configure('stage', 'production', function(){
+ * // executed for stage and production
+ * });
+ *
+ * Note:
+ *
+ * These callbacks are invoked immediately, and
+ * are effectively sugar for the following:
+ *
+ * var env = process.env.NODE_ENV || 'development';
+ *
+ * switch (env) {
+ * case 'development':
+ * ...
+ * break;
+ * case 'stage':
+ * ...
+ * break;
+ * case 'production':
+ * ...
+ * break;
+ * }
+ *
+ * @param {String} env...
+ * @param {Function} fn
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.configure = function(env, fn){
+ var envs = 'all'
+ , args = [].slice.call(arguments);
+ fn = args.pop();
+ if (args.length) envs = args;
+ if ('all' == envs || ~envs.indexOf(this.settings.env)) fn.call(this);
+ return this;
+};
+
+/**
+ * Delegate `.VERB(...)` calls to `router.VERB(...)`.
+ */
+
+methods.forEach(function(method){
+ app[method] = function(path){
+ if ('get' == method && 1 == arguments.length) return this.set(path);
+
+ // if no router attached yet, attach the router
+ if (!this._usedRouter) this.use(this.router);
+
+ // setup route
+ this._router[method].apply(this._router, arguments);
+ return this;
+ };
+});
+
+/**
+ * Special-cased "all" method, applying the given route `path`,
+ * middleware, and callback to _every_ HTTP method.
+ *
+ * @param {String} path
+ * @param {Function} ...
+ * @return {app} for chaining
+ * @api public
+ */
+
+app.all = function(path){
+ var args = arguments;
+ methods.forEach(function(method){
+ app[method].apply(this, args);
+ }, this);
+ return this;
+};
+
+// del -> delete alias
+
+app.del = app.delete;
+
+/**
+ * Render the given view `name` name with `options`
+ * and a callback accepting an error and the
+ * rendered template string.
+ *
+ * Example:
+ *
+ * app.render('email', { name: 'Tobi' }, function(err, html){
+ * // ...
+ * })
+ *
+ * @param {String} name
+ * @param {String|Function} options or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+app.render = function(name, options, fn){
+ var opts = {}
+ , cache = this.cache
+ , engines = this.engines
+ , view;
+
+ // support callback function as second arg
+ if ('function' == typeof options) {
+ fn = options, options = {};
+ }
+
+ // merge app.locals
+ utils.merge(opts, this.locals);
+
+ // merge options._locals
+ if (options._locals) utils.merge(opts, options._locals);
+
+ // merge options
+ utils.merge(opts, options);
+
+ // set .cache unless explicitly provided
+ opts.cache = null == opts.cache
+ ? this.enabled('view cache')
+ : opts.cache;
+
+ // primed cache
+ if (opts.cache) view = cache[name];
+
+ // view
+ if (!view) {
+ view = new (this.get('view'))(name, {
+ defaultEngine: this.get('view engine'),
+ root: this.get('views'),
+ engines: engines
+ });
+
+ if (!view.path) {
+ var err = new Error('Failed to lookup view "' + name + '"');
+ err.view = view;
+ return fn(err);
+ }
+
+ // prime the cache
+ if (opts.cache) cache[name] = view;
+ }
+
+ // render
+ try {
+ view.render(opts, fn);
+ } catch (err) {
+ fn(err);
+ }
+};
+
+/**
+ * Listen for connections.
+ *
+ * A node `http.Server` is returned, with this
+ * application (which is a `Function`) as its
+ * callback. If you wish to create both an HTTP
+ * and HTTPS server you may do so with the "http"
+ * and "https" modules as shown here:
+ *
+ * var http = require('http')
+ * , https = require('https')
+ * , express = require('express')
+ * , app = express();
+ *
+ * http.createServer(app).listen(80);
+ * https.createServer({ ... }, app).listen(443);
+ *
+ * @return {http.Server}
+ * @api public
+ */
+
+app.listen = function(){
+ var server = http.createServer(this);
+ return server.listen.apply(server, arguments);
+};
diff --git a/node_modules/express/lib/express.js b/node_modules/express/lib/express.js
new file mode 100644
index 0000000..ab55889
--- /dev/null
+++ b/node_modules/express/lib/express.js
@@ -0,0 +1,92 @@
+/**
+ * Module dependencies.
+ */
+
+var connect = require('connect')
+ , proto = require('./application')
+ , Route = require('./router/route')
+ , Router = require('./router')
+ , req = require('./request')
+ , res = require('./response')
+ , utils = connect.utils;
+
+/**
+ * Expose `createApplication()`.
+ */
+
+exports = module.exports = createApplication;
+
+/**
+ * Framework version.
+ */
+
+exports.version = '3.2.0';
+
+/**
+ * Expose mime.
+ */
+
+exports.mime = connect.mime;
+
+/**
+ * Create an express application.
+ *
+ * @return {Function}
+ * @api public
+ */
+
+function createApplication() {
+ var app = connect();
+ utils.merge(app, proto);
+ app.request = { __proto__: req };
+ app.response = { __proto__: res };
+ app.init();
+ return app;
+}
+
+/**
+ * Expose connect.middleware as express.*
+ * for example `express.logger` etc.
+ */
+
+for (var key in connect.middleware) {
+ Object.defineProperty(
+ exports
+ , key
+ , Object.getOwnPropertyDescriptor(connect.middleware, key));
+}
+
+/**
+ * Error on createServer().
+ */
+
+exports.createServer = function(){
+ console.warn('Warning: express.createServer() is deprecated, express');
+ console.warn('applications no longer inherit from http.Server,');
+ console.warn('please use:');
+ console.warn('');
+ console.warn(' var express = require("express");');
+ console.warn(' var app = express();');
+ console.warn('');
+ return createApplication();
+};
+
+/**
+ * Expose the prototypes.
+ */
+
+exports.application = proto;
+exports.request = req;
+exports.response = res;
+
+/**
+ * Expose constructors.
+ */
+
+exports.Route = Route;
+exports.Router = Router;
+
+// Error handler title
+
+exports.errorHandler.title = 'Express';
+
diff --git a/node_modules/express/lib/middleware.js b/node_modules/express/lib/middleware.js
new file mode 100644
index 0000000..308c5bb
--- /dev/null
+++ b/node_modules/express/lib/middleware.js
@@ -0,0 +1,33 @@
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('./utils');
+
+/**
+ * Initialization middleware, exposing the
+ * request and response to eachother, as well
+ * as defaulting the X-Powered-By header field.
+ *
+ * @param {Function} app
+ * @return {Function}
+ * @api private
+ */
+
+exports.init = function(app){
+ return function expressInit(req, res, next){
+ req.app = res.app = app;
+ if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
+ req.res = res;
+ res.req = req;
+ req.next = next;
+
+ req.__proto__ = app.request;
+ res.__proto__ = app.response;
+
+ res.locals = res.locals || utils.locals(res);
+
+ next();
+ }
+};
diff --git a/node_modules/express/lib/request.js b/node_modules/express/lib/request.js
new file mode 100644
index 0000000..fd201e3
--- /dev/null
+++ b/node_modules/express/lib/request.js
@@ -0,0 +1,526 @@
+
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+ , utils = require('./utils')
+ , connect = require('connect')
+ , fresh = require('fresh')
+ , parseRange = require('range-parser')
+ , parse = connect.utils.parseUrl
+ , mime = connect.mime;
+
+/**
+ * Request prototype.
+ */
+
+var req = exports = module.exports = {
+ __proto__: http.IncomingMessage.prototype
+};
+
+/**
+ * Return request header.
+ *
+ * The `Referrer` header field is special-cased,
+ * both `Referrer` and `Referer` are interchangeable.
+ *
+ * Examples:
+ *
+ * req.get('Content-Type');
+ * // => "text/plain"
+ *
+ * req.get('content-type');
+ * // => "text/plain"
+ *
+ * req.get('Something');
+ * // => undefined
+ *
+ * Aliased as `req.header()`.
+ *
+ * @param {String} name
+ * @return {String}
+ * @api public
+ */
+
+req.get =
+req.header = function(name){
+ switch (name = name.toLowerCase()) {
+ case 'referer':
+ case 'referrer':
+ return this.headers.referrer
+ || this.headers.referer;
+ default:
+ return this.headers[name];
+ }
+};
+
+/**
+ * Check if the given `type(s)` is acceptable, returning
+ * the best match when true, otherwise `undefined`, in which
+ * case you should respond with 406 "Not Acceptable".
+ *
+ * The `type` value may be a single mime type string
+ * such as "application/json", the extension name
+ * such as "json", a comma-delimted list such as "json, html, text/plain",
+ * or an array `["json", "html", "text/plain"]`. When a list
+ * or array is given the _best_ match, if any is returned.
+ *
+ * Examples:
+ *
+ * // Accept: text/html
+ * req.accepts('html');
+ * // => "html"
+ *
+ * // Accept: text/*, application/json
+ * req.accepts('html');
+ * // => "html"
+ * req.accepts('text/html');
+ * // => "text/html"
+ * req.accepts('json, text');
+ * // => "json"
+ * req.accepts('application/json');
+ * // => "application/json"
+ *
+ * // Accept: text/*, application/json
+ * req.accepts('image/png');
+ * req.accepts('png');
+ * // => undefined
+ *
+ * // Accept: text/*;q=.5, application/json
+ * req.accepts(['html', 'json']);
+ * req.accepts('html, json');
+ * // => "json"
+ *
+ * @param {String|Array} type(s)
+ * @return {String}
+ * @api public
+ */
+
+req.accepts = function(type){
+ return utils.accepts(type, this.get('Accept'));
+};
+
+/**
+ * Check if the given `encoding` is accepted.
+ *
+ * @param {String} encoding
+ * @return {Boolean}
+ * @api public
+ */
+
+req.acceptsEncoding = function(encoding){
+ return ~this.acceptedEncodings.indexOf(encoding);
+};
+
+/**
+ * Check if the given `charset` is acceptable,
+ * otherwise you should respond with 406 "Not Acceptable".
+ *
+ * @param {String} charset
+ * @return {Boolean}
+ * @api public
+ */
+
+req.acceptsCharset = function(charset){
+ var accepted = this.acceptedCharsets;
+ return accepted.length
+ ? ~accepted.indexOf(charset)
+ : true;
+};
+
+/**
+ * Check if the given `lang` is acceptable,
+ * otherwise you should respond with 406 "Not Acceptable".
+ *
+ * @param {String} lang
+ * @return {Boolean}
+ * @api public
+ */
+
+req.acceptsLanguage = function(lang){
+ var accepted = this.acceptedLanguages;
+ return accepted.length
+ ? ~accepted.indexOf(lang)
+ : true;
+};
+
+/**
+ * Parse Range header field,
+ * capping to the given `size`.
+ *
+ * Unspecified ranges such as "0-" require
+ * knowledge of your resource length. In
+ * the case of a byte range this is of course
+ * the total number of bytes. If the Range
+ * header field is not given `null` is returned,
+ * `-1` when unsatisfiable, `-2` when syntactically invalid.
+ *
+ * NOTE: remember that ranges are inclusive, so
+ * for example "Range: users=0-3" should respond
+ * with 4 users when available, not 3.
+ *
+ * @param {Number} size
+ * @return {Array}
+ * @api public
+ */
+
+req.range = function(size){
+ var range = this.get('Range');
+ if (!range) return;
+ return parseRange(size, range);
+};
+
+/**
+ * Return an array of encodings.
+ *
+ * Examples:
+ *
+ * ['gzip', 'deflate']
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('acceptedEncodings', function(){
+ var accept = this.get('Accept-Encoding');
+ return accept
+ ? accept.trim().split(/ *, */)
+ : [];
+});
+
+/**
+ * Return an array of Accepted media types
+ * ordered from highest quality to lowest.
+ *
+ * Examples:
+ *
+ * [ { value: 'application/json',
+ * quality: 1,
+ * type: 'application',
+ * subtype: 'json' },
+ * { value: 'text/html',
+ * quality: 0.5,
+ * type: 'text',
+ * subtype: 'html' } ]
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('accepted', function(){
+ var accept = this.get('Accept');
+ return accept
+ ? utils.parseAccept(accept)
+ : [];
+});
+
+/**
+ * Return an array of Accepted languages
+ * ordered from highest quality to lowest.
+ *
+ * Examples:
+ *
+ * Accept-Language: en;q=.5, en-us
+ * ['en-us', 'en']
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('acceptedLanguages', function(){
+ var accept = this.get('Accept-Language');
+ return accept
+ ? utils
+ .parseParams(accept)
+ .map(function(obj){
+ return obj.value;
+ })
+ : [];
+});
+
+/**
+ * Return an array of Accepted charsets
+ * ordered from highest quality to lowest.
+ *
+ * Examples:
+ *
+ * Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8
+ * ['unicode-1-1', 'iso-8859-5']
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('acceptedCharsets', function(){
+ var accept = this.get('Accept-Charset');
+ return accept
+ ? utils
+ .parseParams(accept)
+ .map(function(obj){
+ return obj.value;
+ })
+ : [];
+});
+
+/**
+ * Return the value of param `name` when present or `defaultValue`.
+ *
+ * - Checks route placeholders, ex: _/user/:id_
+ * - Checks body params, ex: id=12, {"id":12}
+ * - Checks query string params, ex: ?id=12
+ *
+ * To utilize request bodies, `req.body`
+ * should be an object. This can be done by using
+ * the `connect.bodyParser()` middleware.
+ *
+ * @param {String} name
+ * @param {Mixed} [defaultValue]
+ * @return {String}
+ * @api public
+ */
+
+req.param = function(name, defaultValue){
+ var params = this.params || {};
+ var body = this.body || {};
+ var query = this.query || {};
+ if (null != params[name] && params.hasOwnProperty(name)) return params[name];
+ if (null != body[name]) return body[name];
+ if (null != query[name]) return query[name];
+ return defaultValue;
+};
+
+/**
+ * Check if the incoming request contains the "Content-Type"
+ * header field, and it contains the give mime `type`.
+ *
+ * Examples:
+ *
+ * // With Content-Type: text/html; charset=utf-8
+ * req.is('html');
+ * req.is('text/html');
+ * req.is('text/*');
+ * // => true
+ *
+ * // When Content-Type is application/json
+ * req.is('json');
+ * req.is('application/json');
+ * req.is('application/*');
+ * // => true
+ *
+ * req.is('html');
+ * // => false
+ *
+ * @param {String} type
+ * @return {Boolean}
+ * @api public
+ */
+
+req.is = function(type){
+ var ct = this.get('Content-Type');
+ if (!ct) return false;
+ ct = ct.split(';')[0];
+ if (!~type.indexOf('/')) type = mime.lookup(type);
+ if (~type.indexOf('*')) {
+ type = type.split('/');
+ ct = ct.split('/');
+ if ('*' == type[0] && type[1] == ct[1]) return true;
+ if ('*' == type[1] && type[0] == ct[0]) return true;
+ return false;
+ }
+ return !! ~ct.indexOf(type);
+};
+
+/**
+ * Return the protocol string "http" or "https"
+ * when requested with TLS. When the "trust proxy"
+ * setting is enabled the "X-Forwarded-Proto" header
+ * field will be trusted. If you're running behind
+ * a reverse proxy that supplies https for you this
+ * may be enabled.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('protocol', function(){
+ var trustProxy = this.app.get('trust proxy');
+ return this.connection.encrypted
+ ? 'https'
+ : trustProxy
+ ? (this.get('X-Forwarded-Proto') || 'http')
+ : 'http';
+});
+
+/**
+ * Short-hand for:
+ *
+ * req.protocol == 'https'
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('secure', function(){
+ return 'https' == this.protocol;
+});
+
+/**
+ * Return the remote address, or when
+ * "trust proxy" is `true` return
+ * the upstream addr.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('ip', function(){
+ return this.ips[0] || this.connection.remoteAddress;
+});
+
+/**
+ * When "trust proxy" is `true`, parse
+ * the "X-Forwarded-For" ip address list.
+ *
+ * For example if the value were "client, proxy1, proxy2"
+ * you would receive the array `["client", "proxy1", "proxy2"]`
+ * where "proxy2" is the furthest down-stream.
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('ips', function(){
+ var trustProxy = this.app.get('trust proxy');
+ var val = this.get('X-Forwarded-For');
+ return trustProxy && val
+ ? val.split(/ *, */)
+ : [];
+});
+
+/**
+ * Return basic auth credentials.
+ *
+ * Examples:
+ *
+ * // http://tobi:hello@example.com
+ * req.auth
+ * // => { username: 'tobi', password: 'hello' }
+ *
+ * @return {Object} or undefined
+ * @api public
+ */
+
+req.__defineGetter__('auth', function(){
+ // missing
+ var auth = this.get('Authorization');
+ if (!auth) return;
+
+ // malformed
+ var parts = auth.split(' ');
+ if ('basic' != parts[0].toLowerCase()) return;
+ if (!parts[1]) return;
+ auth = parts[1];
+
+ // credentials
+ auth = new Buffer(auth, 'base64').toString().match(/^([^:]*):(.*)$/);
+ if (!auth) return;
+ return { username: auth[1], password: auth[2] };
+});
+
+/**
+ * Return subdomains as an array.
+ *
+ * Subdomains are the dot-separated parts of the host before the main domain of
+ * the app. By default, the domain of the app is assumed to be the last two
+ * parts of the host. This can be changed by setting "subdomain offset".
+ *
+ * For example, if the domain is "tobi.ferrets.example.com":
+ * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
+ * If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
+ *
+ * @return {Array}
+ * @api public
+ */
+
+req.__defineGetter__('subdomains', function(){
+ var offset = this.app.get('subdomain offset');
+ return this.get('Host')
+ .split('.')
+ .reverse()
+ .slice(offset);
+});
+
+/**
+ * Short-hand for `url.parse(req.url).pathname`.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('path', function(){
+ return parse(this).pathname;
+});
+
+/**
+ * Parse the "Host" header field hostname.
+ *
+ * @return {String}
+ * @api public
+ */
+
+req.__defineGetter__('host', function(){
+ var trustProxy = this.app.get('trust proxy');
+ var host = trustProxy && this.get('X-Forwarded-Host');
+ host = host || this.get('Host');
+ return host.split(':')[0];
+});
+
+/**
+ * Check if the request is fresh, aka
+ * Last-Modified and/or the ETag
+ * still match.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('fresh', function(){
+ var method = this.method;
+ var s = this.res.statusCode;
+
+ // GET or HEAD for weak freshness validation only
+ if ('GET' != method && 'HEAD' != method) return false;
+
+ // 2xx or 304 as per rfc2616 14.26
+ if ((s >= 200 && s < 300) || 304 == s) {
+ return fresh(this.headers, this.res._headers);
+ }
+
+ return false;
+});
+
+/**
+ * Check if the request is stale, aka
+ * "Last-Modified" and / or the "ETag" for the
+ * resource has changed.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('stale', function(){
+ return !this.fresh;
+});
+
+/**
+ * Check if the request was an _XMLHttpRequest_.
+ *
+ * @return {Boolean}
+ * @api public
+ */
+
+req.__defineGetter__('xhr', function(){
+ var val = this.get('X-Requested-With') || '';
+ return 'xmlhttprequest' == val.toLowerCase();
+});
diff --git a/node_modules/express/lib/response.js b/node_modules/express/lib/response.js
new file mode 100644
index 0000000..50fcd05
--- /dev/null
+++ b/node_modules/express/lib/response.js
@@ -0,0 +1,756 @@
+/**
+ * Module dependencies.
+ */
+
+var http = require('http')
+ , path = require('path')
+ , connect = require('connect')
+ , utils = connect.utils
+ , sign = require('cookie-signature').sign
+ , normalizeType = require('./utils').normalizeType
+ , normalizeTypes = require('./utils').normalizeTypes
+ , etag = require('./utils').etag
+ , statusCodes = http.STATUS_CODES
+ , cookie = require('cookie')
+ , send = require('send')
+ , mime = connect.mime
+ , basename = path.basename
+ , extname = path.extname
+ , join = path.join;
+
+/**
+ * Response prototype.
+ */
+
+var res = module.exports = {
+ __proto__: http.ServerResponse.prototype
+};
+
+/**
+ * Set status `code`.
+ *
+ * @param {Number} code
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.status = function(code){
+ this.statusCode = code;
+ return this;
+};
+
+/**
+ * Set Link header field with the given `links`.
+ *
+ * Examples:
+ *
+ * res.links({
+ * next: 'http://api.example.com/users?page=2',
+ * last: 'http://api.example.com/users?page=5'
+ * });
+ *
+ * @param {Object} links
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.links = function(links){
+ return this.set('Link', Object.keys(links).map(function(rel){
+ return '<' + links[rel] + '>; rel="' + rel + '"';
+ }).join(', '));
+};
+
+/**
+ * Send a response.
+ *
+ * Examples:
+ *
+ * res.send(new Buffer('wahoo'));
+ * res.send({ some: 'json' });
+ * res.send('<p>some html</p>');
+ * res.send(404, 'Sorry, cant find that');
+ * res.send(404);
+ *
+ * @param {Mixed} body or status
+ * @param {Mixed} body
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.send = function(body){
+ var req = this.req
+ , head = 'HEAD' == req.method
+ , len;
+
+ // allow status / body
+ if (2 == arguments.length) {
+ // res.send(body, status) backwards compat
+ if ('number' != typeof body && 'number' == typeof arguments[1]) {
+ this.statusCode = arguments[1];
+ } else {
+ this.statusCode = body;
+ body = arguments[1];
+ }
+ }
+
+ switch (typeof body) {
+ // response status
+ case 'number':
+ this.get('Content-Type') || this.type('txt');
+ this.statusCode = body;
+ body = http.STATUS_CODES[body];
+ break;
+ // string defaulting to html
+ case 'string':
+ if (!this.get('Content-Type')) {
+ this.charset = this.charset || 'utf-8';
+ this.type('html');
+ }
+ break;
+ case 'boolean':
+ case 'object':
+ if (null == body) {
+ body = '';
+ } else if (Buffer.isBuffer(body)) {
+ this.get('Content-Type') || this.type('bin');
+ } else {
+ return this.json(body);
+ }
+ break;
+ }
+
+ // populate Content-Length
+ if (undefined !== body && !this.get('Content-Length')) {
+ this.set('Content-Length', len = Buffer.isBuffer(body)
+ ? body.length
+ : Buffer.byteLength(body));
+ }
+
+ // ETag support
+ // TODO: W/ support
+ if (len > 1024) {
+ if (!this.get('ETag')) {
+ this.set('ETag', etag(body));
+ }
+ }
+
+ // freshness
+ if (req.fresh) this.statusCode = 304;
+
+ // strip irrelevant headers
+ if (204 == this.statusCode || 304 == this.statusCode) {
+ this.removeHeader('Content-Type');
+ this.removeHeader('Content-Length');
+ this.removeHeader('Transfer-Encoding');
+ body = '';
+ }
+
+ // respond
+ this.end(head ? null : body);
+ return this;
+};
+
+/**
+ * Send JSON response.
+ *
+ * Examples:
+ *
+ * res.json(null);
+ * res.json({ user: 'tj' });
+ * res.json(500, 'oh noes!');
+ * res.json(404, 'I dont have that');
+ *
+ * @param {Mixed} obj or status
+ * @param {Mixed} obj
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.json = function(obj){
+ // allow status / body
+ if (2 == arguments.length) {
+ // res.json(body, status) backwards compat
+ if ('number' == typeof arguments[1]) {
+ this.statusCode = arguments[1];
+ } else {
+ this.statusCode = obj;
+ obj = arguments[1];
+ }
+ }
+
+ // settings
+ var app = this.app;
+ var replacer = app.get('json replacer');
+ var spaces = app.get('json spaces');
+ var body = JSON.stringify(obj, replacer, spaces);
+
+ // content-type
+ this.charset = this.charset || 'utf-8';
+ this.get('Content-Type') || this.set('Content-Type', 'application/json');
+
+ return this.send(body);
+};
+
+/**
+ * Send JSON response with JSONP callback support.
+ *
+ * Examples:
+ *
+ * res.jsonp(null);
+ * res.jsonp({ user: 'tj' });
+ * res.jsonp(500, 'oh noes!');
+ * res.jsonp(404, 'I dont have that');
+ *
+ * @param {Mixed} obj or status
+ * @param {Mixed} obj
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.jsonp = function(obj){
+ // allow status / body
+ if (2 == arguments.length) {
+ // res.json(body, status) backwards compat
+ if ('number' == typeof arguments[1]) {
+ this.statusCode = arguments[1];
+ } else {
+ this.statusCode = obj;
+ obj = arguments[1];
+ }
+ }
+
+ // settings
+ var app = this.app;
+ var replacer = app.get('json replacer');
+ var spaces = app.get('json spaces');
+ var body = JSON.stringify(obj, replacer, spaces)
+ .replace(/\u2028/g, '\\u2028')
+ .replace(/\u2029/g, '\\u2029');
+ var callback = this.req.query[app.get('jsonp callback name')];
+
+ // content-type
+ this.charset = this.charset || 'utf-8';
+ this.set('Content-Type', 'application/json');
+
+ // jsonp
+ if (callback) {
+ this.set('Content-Type', 'text/javascript');
+ var cb = callback.replace(/[^\[\]\w$.]/g, '');
+ body = cb + ' && ' + cb + '(' + body + ');';
+ }
+
+ return this.send(body);
+};
+
+/**
+ * Transfer the file at the given `path`.
+ *
+ * Automatically sets the _Content-Type_ response header field.
+ * The callback `fn(err)` is invoked when the transfer is complete
+ * or when an error occurs. Be sure to check `res.sentHeader`
+ * if you wish to attempt responding, as the header and some data
+ * may have already been transferred.
+ *
+ * Options:
+ *
+ * - `maxAge` defaulting to 0
+ * - `root` root directory for relative filenames
+ *
+ * Examples:
+ *
+ * The following example illustrates how `res.sendfile()` may
+ * be used as an alternative for the `static()` middleware for
+ * dynamic situations. The code backing `res.sendfile()` is actually
+ * the same code, so HTTP cache support etc is identical.
+ *
+ * app.get('/user/:uid/photos/:file', function(req, res){
+ * var uid = req.params.uid
+ * , file = req.params.file;
+ *
+ * req.user.mayViewFilesFrom(uid, function(yes){
+ * if (yes) {
+ * res.sendfile('/uploads/' + uid + '/' + file);
+ * } else {
+ * res.send(403, 'Sorry! you cant see that.');
+ * }
+ * });
+ * });
+ *
+ * @param {String} path
+ * @param {Object|Function} options or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+res.sendfile = function(path, options, fn){
+ var self = this
+ , req = self.req
+ , next = this.req.next
+ , options = options || {}
+ , done;
+
+ // support function as second arg
+ if ('function' == typeof options) {
+ fn = options;
+ options = {};
+ }
+
+ // socket errors
+ req.socket.on('error', error);
+
+ // errors
+ function error(err) {
+ if (done) return;
+ done = true;
+
+ // clean up
+ cleanup();
+ if (!self.headerSent) self.removeHeader('Content-Disposition');
+
+ // callback available
+ if (fn) return fn(err);
+
+ // list in limbo if there's no callback
+ if (self.headerSent) return;
+
+ // delegate
+ next(err);
+ }
+
+ // streaming
+ function stream() {
+ if (done) return;
+ cleanup();
+ if (fn) self.on('finish', fn);
+ }
+
+ // cleanup
+ function cleanup() {
+ req.socket.removeListener('error', error);
+ }
+
+ // transfer
+ var file = send(req, path);
+ if (options.root) file.root(options.root);
+ file.maxage(options.maxAge || 0);
+ file.on('error', error);
+ file.on('directory', next);
+ file.on('stream', stream);
+ file.pipe(this);
+ this.on('finish', cleanup);
+};
+
+/**
+ * Transfer the file at the given `path` as an attachment.
+ *
+ * Optionally providing an alternate attachment `filename`,
+ * and optional callback `fn(err)`. The callback is invoked
+ * when the data transfer is complete, or when an error has
+ * ocurred. Be sure to check `res.headerSent` if you plan to respond.
+ *
+ * This method uses `res.sendfile()`.
+ *
+ * @param {String} path
+ * @param {String|Function} filename or fn
+ * @param {Function} fn
+ * @api public
+ */
+
+res.download = function(path, filename, fn){
+ // support function as second arg
+ if ('function' == typeof filename) {
+ fn = filename;
+ filename = null;
+ }
+
+ filename = filename || path;
+ this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"');
+ return this.sendfile(path, fn);
+};
+
+/**
+ * Set _Content-Type_ response header with `type` through `mime.lookup()`
+ * when it does not contain "/", or set the Content-Type to `type` otherwise.
+ *
+ * Examples:
+ *
+ * res.type('.html');
+ * res.type('html');
+ * res.type('json');
+ * res.type('application/json');
+ * res.type('png');
+ *
+ * @param {String} type
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.contentType =
+res.type = function(type){
+ return this.set('Content-Type', ~type.indexOf('/')
+ ? type
+ : mime.lookup(type));
+};
+
+/**
+ * Respond to the Acceptable formats using an `obj`
+ * of mime-type callbacks.
+ *
+ * This method uses `req.accepted`, an array of
+ * acceptable types ordered by their quality values.
+ * When "Accept" is not present the _first_ callback
+ * is invoked, otherwise the first match is used. When
+ * no match is performed the server responds with
+ * 406 "Not Acceptable".
+ *
+ * Content-Type is set for you, however if you choose
+ * you may alter this within the callback using `res.type()`
+ * or `res.set('Content-Type', ...)`.
+ *
+ * res.format({
+ * 'text/plain': function(){
+ * res.send('hey');
+ * },
+ *
+ * 'text/html': function(){
+ * res.send('<p>hey</p>');
+ * },
+ *
+ * 'appliation/json': function(){
+ * res.send({ message: 'hey' });
+ * }
+ * });
+ *
+ * In addition to canonicalized MIME types you may
+ * also use extnames mapped to these types:
+ *
+ * res.format({
+ * text: function(){
+ * res.send('hey');
+ * },
+ *
+ * html: function(){
+ * res.send('<p>hey</p>');
+ * },
+ *
+ * json: function(){
+ * res.send({ message: 'hey' });
+ * }
+ * });
+ *
+ * By default Express passes an `Error`
+ * with a `.status` of 406 to `next(err)`
+ * if a match is not made. If you provide
+ * a `.default` callback it will be invoked
+ * instead.
+ *
+ * @param {Object} obj
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.format = function(obj){
+ var req = this.req
+ , next = req.next;
+
+ var fn = obj.default;
+ if (fn) delete obj.default;
+ var keys = Object.keys(obj);
+
+ var key = req.accepts(keys);
+
+ this.set('Vary', 'Accept');
+
+ if (key) {
+ this.set('Content-Type', normalizeType(key).value);
+ obj[key](req, this, next);
+ } else if (fn) {
+ fn();
+ } else {
+ var err = new Error('Not Acceptable');
+ err.status = 406;
+ err.types = normalizeTypes(keys).map(function(o){ return o.value });
+ next(err);
+ }
+
+ return this;
+};
+
+/**
+ * Set _Content-Disposition_ header to _attachment_ with optional `filename`.
+ *
+ * @param {String} filename
+ * @return {ServerResponse}
+ * @api public
+ */
+
+res.attachment = function(filename){
+ if (filename) this.type(extname(filename));
+ this.set('Content-Disposition', filename
+ ? 'attachment; filename="' + basename(filename) + '"'
+ : 'attachment');
+ return this;
+};
+
+/**
+ * Set header `field` to `val`, or pass
+ * an object of header fields.
+ *
+ * Examples:
+ *
+ * res.set('Foo', ['bar', 'baz']);
+ * res.set('Accept', 'application/json');
+ * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
+ *
+ * Aliased as `res.header()`.
+ *
+ * @param {String|Object|Array} field
+ * @param {String} val
+ * @return {ServerResponse} for chaining
+ * @api public
+ */
+
+res.set =
+res.header = function(field, val){
+ if (2 == arguments.length) {
+ if (Array.isArray(val)) val = val.map(String);
+ else val = String(val);
+ this.setHeader(field, val);
+ } else {
+ for (var key in field) {
+ this.set(key, field[key]);
+ }
+ }
+ return this;
+};
+
+/**
+ * Get value for header `field`.
+ *
+ * @param {String} field
+ * @return {String}
+ * @api public
+ */
+
+res.get = function(field){
+ return this.getHeader(field);
+};
+
+/**
+ * Clear cookie `name`.
+ *
+ * @param {String} name
+ * @param {Object} options
+ * @param {ServerResponse} for chaining
+ * @api public
+ */
+
+res.clearCookie = function(name, options){
+ var opts = { expires: new Date(1), path: '/' };
+ return this.cookie(name, '', options
+ ? utils.merge(opts, options)
+ : opts);
+};
+
+/**
+ * Set cookie `name` to `val`, with the given `options`.
+ *
+ * Options:
+ *
+ * - `maxAge` max-age in milliseconds, converted to `expires`
+ * - `signed` sign the cookie
+ * - `path` defaults to "/"
+ *
+ * Examples:
+ *
+ * // "Remember Me" for 15 minutes
+ * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
+ *
+ * // save as above
+ * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
+ *
+ * @param {String} name
+ * @param {String|Object} val
+ * @param {Options} options
+ * @api public
+ */
+
+res.cookie = function(name, val, options){
+ options = utils.merge({}, options);
+ var secret = this.req.secret;
+ var signed = options.signed;
+ if (signed && !secret) throw new Error('connect.cookieParser("secret") required for signed cookies');
+ if ('object' == typeof val) val = 'j:' + JSON.stringify(val);
+ if (signed) val = 's:' + sign(val, secret);
+ if ('maxAge' in options) {
+ options.expires = new Date(Date.now() + options.maxAge);
+ options.maxAge /= 1000;
+ }
+ if (null == options.path) options.path = '/';
+ this.set('Set-Cookie', cookie.serialize(name, String(val), options));
+ return this;
+};
+
+
+/**
+ * Set the location header to `url`.
+ *
+ * The given `url` can also be the name of a mapped url, for
+ * example by default express supports "back" which redirects
+ * to the _Referrer_ or _Referer_ headers or "/".
+ *
+ * Examples:
+ *
+ * res.location('/foo/bar').;
+ * res.location('http://example.com');
+ * res.location('../login'); // /blog/post/1 -> /blog/login
+ *
+ * Mounting:
+ *
+ * When an application is mounted and `res.location()`
+ * is given a path that does _not_ lead with "/" it becomes
+ * relative to the mount-point. For example if the application
+ * is mounted at "/blog", the following would become "/blog/login".
+ *
+ * res.location('login');
+ *
+ * While the leading slash would result in a location of "/login":
+ *
+ * res.location('/login');
+ *
+ * @param {String} url
+ * @api public
+ */
+
+res.location = function(url){
+ var app = this.app
+ , req = this.req;
+
+ // setup redirect map
+ var map = { back: req.get('Referrer') || '/' };
+
+ // perform redirect
+ url = map[url] || url;
+
+ // relative
+ if (!~url.indexOf('://') && 0 != url.indexOf('//')) {
+ var path
+
+ // relative to path
+ if ('.' == url[0]) {
+ path = req.originalUrl.split('?')[0]
+ url = path + ('/' == path[path.length - 1] ? '' : '/') + url;
+ // relative to mount-point
+ } else if ('/' != url[0]) {
+ path = app.path();
+ url = path + '/' + url;
+ }
+ }
+
+ // Respond
+ this.set('Location', url);
+ return this;
+};
+
+/**
+ * Redirect to the given `url` with optional response `status`
+ * defaulting to 302.
+ *
+ * The resulting `url` is determined by `res.location()`, so
+ * it will play nicely with mounted apps, relative paths,
+ * `"back"` etc.
+ *
+ * Examples:
+ *
+ * res.redirect('/foo/bar');
+ * res.redirect('http://example.com');
+ * res.redirect(301, 'http://example.com');
+ * res.redirect('http://example.com', 301);
+ * res.redirect('../login'); // /blog/post/1 -> /blog/login
+ *
+ * @param {String} url
+ * @param {Number} code
+ * @api public
+ */
+
+res.redirect = function(url){
+ var app = this.app
+ , head = 'HEAD' == this.req.method
+ , status = 302
+ , body;
+
+ // allow status / url
+ if (2 == arguments.length) {
+ if ('number' == typeof url) {
+ status = url;
+ url = arguments[1];
+ } else {
+ status = arguments[1];
+ }
+ }
+
+ // Set location header
+ this.location(url);
+ url = this.get('Location');
+
+ // Support text/{plain,html} by default
+ this.format({
+ text: function(){
+ body = statusCodes[status] + '. Redirecting to ' + encodeURI(url);
+ },
+
+ html: function(){
+ var u = utils.escape(url);
+ body = '<p>' + statusCodes[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>';
+ },
+
+ default: function(){
+ body = '';
+ }
+ });
+
+ // Respond
+ this.statusCode = status;
+ this.set('Content-Length', Buffer.byteLength(body));
+ this.end(head ? null : body);
+};
+
+/**
+ * Render `view` with the given `options` and optional callback `fn`.
+ * When a callback function is given a response will _not_ be made
+ * automatically, otherwise a response of _200_ and _text/html_ is given.
+ *
+ * Options:
+ *
+ * - `cache` boolean hinting to the engine it should cache
+ * - `filename` filename of the view being rendered
+ *
+ * @param {String} view
+ * @param {Object|Function} options or callback function
+ * @param {Function} fn
+ * @api public
+ */
+
+res.render = function(view, options, fn){
+ var self = this
+ , options = options || {}
+ , req = this.req
+ , app = req.app;
+
+ // support callback function as second arg
+ if ('function' == typeof options) {
+ fn = options, options = {};
+ }
+
+ // merge res.locals
+ options._locals = self.locals;
+
+ // default callback to respond
+ fn = fn || function(err, str){
+ if (err) return req.next(err);
+ self.send(str);
+ };
+
+ // render
+ app.render(view, options, fn);
+};
diff --git a/node_modules/express/lib/router/index.js b/node_modules/express/lib/router/index.js
new file mode 100644
index 0000000..662dc29
--- /dev/null
+++ b/node_modules/express/lib/router/index.js
@@ -0,0 +1,273 @@
+/**
+ * Module dependencies.
+ */
+
+var Route = require('./route')
+ , utils = require('../utils')
+ , methods = require('methods')
+ , debug = require('debug')('express:router')
+ , parse = require('connect').utils.parseUrl;
+
+/**
+ * Expose `Router` constructor.
+ */
+
+exports = module.exports = Router;
+
+/**
+ * Initialize a new `Router` with the given `options`.
+ *
+ * @param {Object} options
+ * @api private
+ */
+
+function Router(options) {
+ options = options || {};
+ var self = this;
+ this.map = {};
+ this.params = {};
+ this._params = [];
+ this.caseSensitive = options.caseSensitive;
+ this.strict = options.strict;
+ this.middleware = function router(req, res, next){
+ self._dispatch(req, res, next);
+ };
+}
+
+/**
+ * Register a param callback `fn` for the given `name`.
+ *
+ * @param {String|Function} name
+ * @param {Function} fn
+ * @return {Router} for chaining
+ * @api public
+ */
+
+Router.prototype.param = function(name, fn){
+ // param logic
+ if ('function' == typeof name) {
+ this._params.push(name);
+ return;
+ }
+
+ // apply param functions
+ var params = this._params
+ , len = params.length
+ , ret;
+
+ for (var i = 0; i < len; ++i) {
+ if (ret = params[i](name, fn)) {
+ fn = ret;
+ }
+ }
+
+ // ensure we end up with a
+ // middleware function
+ if ('function' != typeof fn) {
+ throw new Error('invalid param() call for ' + name + ', got ' + fn);
+ }
+
+ (this.params[name] = this.params[name] || []).push(fn);
+ return this;
+};
+
+/**
+ * Route dispatcher aka the route "middleware".
+ *
+ * @param {IncomingMessage} req
+ * @param {ServerResponse} res
+ * @param {Function} next
+ * @api private
+ */
+
+Router.prototype._dispatch = function(req, res, next){
+ var params = this.params
+ , self = this;
+
+ debug('dispatching %s %s (%s)', req.method, req.url, req.originalUrl);
+
+ // route dispatch
+ (function pass(i, err){
+ var paramCallbacks
+ , paramIndex = 0
+ , paramVal
+ , route
+ , keys
+ , key;
+
+ // match next route
+ function nextRoute(err) {
+ pass(req._route_index + 1, err);
+ }
+
+ // match route
+ req.route = route = self.matchRequest(req, i);
+
+ // no route
+ if (!route) return next(err);
+ debug('matched %s %s', route.method, route.path);
+
+ // we have a route
+ // start at param 0
+ req.params = route.params;
+ keys = route.keys;
+ i = 0;
+
+ // param callbacks
+ function param(err) {
+ paramIndex = 0;
+ key = keys[i++];
+ paramVal = key && req.params[key.name];
+ paramCallbacks = key && params[key.name];
+
+ try {
+ if ('route' == err) {
+ nextRoute();
+ } else if (err) {
+ i = 0;
+ callbacks(err);
+ } else if (paramCallbacks && undefined !== paramVal) {
+ paramCallback();
+ } else if (key) {
+ param();
+ } else {
+ i = 0;
+ callbacks();
+ }
+ } catch (err) {
+ param(err);
+ }
+ };
+
+ param(err);
+
+ // single param callbacks
+ function paramCallback(err) {
+ var fn = paramCallbacks[paramIndex++];
+ if (err || !fn) return param(err);
+ fn(req, res, paramCallback, paramVal, key.name);
+ }
+
+ // invoke route callbacks
+ function callbacks(err) {
+ var fn = route.callbacks[i++];
+ try {
+ if ('route' == err) {
+ nextRoute();
+ } else if (err && fn) {
+ if (fn.length < 4) return callbacks(err);
+ fn(err, req, res, callbacks);
+ } else if (fn) {
+ if (fn.length < 4) return fn(req, res, callbacks);
+ callbacks();
+ } else {
+ nextRoute(err);
+ }
+ } catch (err) {
+ callbacks(err);
+ }
+ }
+ })(0);
+};
+
+/**
+ * Attempt to match a route for `req`
+ * with optional starting index of `i`
+ * defaulting to 0.
+ *
+ * @param {IncomingMessage} req
+ * @param {Number} i
+ * @return {Route}
+ * @api private
+ */
+
+Router.prototype.matchRequest = function(req, i, head){
+ var method = req.method.toLowerCase()
+ , url = parse(req)
+ , path = url.pathname
+ , routes = this.map
+ , i = i || 0
+ , route;
+
+ // HEAD support
+ if (!head && 'head' == method) {
+ route = this.matchRequest(req, i, true);
+ if (route) return route;
+ method = 'get';
+ }
+
+ // routes for this method
+ if (routes = routes[method]) {
+
+ // matching routes
+ for (var len = routes.length; i < len; ++i) {
+ route = routes[i];
+ if (route.match(path)) {
+ req._route_index = i;
+ return route;
+ }
+ }
+ }
+};
+
+/**
+ * Attempt to match a route for `method`
+ * and `url` with optional starting
+ * index of `i` defaulting to 0.
+ *
+ * @param {String} method
+ * @param {String} url
+ * @param {Number} i
+ * @return {Route}
+ * @api private
+ */
+
+Router.prototype.match = function(method, url, i, head){
+ var req = { method: method, url: url };
+ return this.matchRequest(req, i, head);
+};
+
+/**
+ * Route `method`, `path`, and one or more callbacks.
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Function} callback...
+ * @return {Router} for chaining
+ * @api private
+ */
+
+Router.prototype.route = function(method, path, callbacks){
+ var method = method.toLowerCase()
+ , callbacks = utils.flatten([].slice.call(arguments, 2));
+
+ // ensure path was given
+ if (!path) throw new Error('Router#' + method + '() requires a path');
+
+ // ensure all callbacks are functions
+ callbacks.forEach(function(fn, i){
+ if ('function' == typeof fn) return;
+ var type = {}.toString.call(fn);
+ var msg = '.' + method + '() requires callback functions but got a ' + type;
+ throw new Error(msg);
+ });
+
+ // create the route
+ debug('defined %s %s', method, path);
+ var route = new Route(method, path, callbacks, {
+ sensitive: this.caseSensitive,
+ strict: this.strict
+ });
+
+ // add it
+ (this.map[method] = this.map[method] || []).push(route);
+ return this;
+};
+
+methods.forEach(function(method){
+ Router.prototype[method] = function(path){
+ var args = [method].concat([].slice.call(arguments));
+ this.route.apply(this, args);
+ return this;
+ };
+});
diff --git a/node_modules/express/lib/router/route.js b/node_modules/express/lib/router/route.js
new file mode 100644
index 0000000..c1a0b5e
--- /dev/null
+++ b/node_modules/express/lib/router/route.js
@@ -0,0 +1,72 @@
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils');
+
+/**
+ * Expose `Route`.
+ */
+
+module.exports = Route;
+
+/**
+ * Initialize `Route` with the given HTTP `method`, `path`,
+ * and an array of `callbacks` and `options`.
+ *
+ * Options:
+ *
+ * - `sensitive` enable case-sensitive routes
+ * - `strict` enable strict matching for trailing slashes
+ *
+ * @param {String} method
+ * @param {String} path
+ * @param {Array} callbacks
+ * @param {Object} options.
+ * @api private
+ */
+
+function Route(method, path, callbacks, options) {
+ options = options || {};
+ this.path = path;
+ this.method = method;
+ this.callbacks = callbacks;
+ this.regexp = utils.pathRegexp(path
+ , this.keys = []
+ , options.sensitive
+ , options.strict);
+}
+
+/**
+ * Check if this route matches `path`, if so
+ * populate `.params`.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+Route.prototype.match = function(path){
+ var keys = this.keys
+ , params = this.params = []
+ , m = this.regexp.exec(path);
+
+ if (!m) return false;
+
+ for (var i = 1, len = m.length; i < len; ++i) {
+ var key = keys[i - 1];
+
+ var val = 'string' == typeof m[i]
+ ? decodeURIComponent(m[i])
+ : m[i];
+
+ if (key) {
+ params[key.name] = val;
+ } else {
+ params.push(val);
+ }
+ }
+
+ return true;
+};
diff --git a/node_modules/express/lib/utils.js b/node_modules/express/lib/utils.js
new file mode 100644
index 0000000..fd245a8
--- /dev/null
+++ b/node_modules/express/lib/utils.js
@@ -0,0 +1,313 @@
+
+/**
+ * Module dependencies.
+ */
+
+var mime = require('connect').mime
+ , crc32 = require('buffer-crc32');
+
+/**
+ * toString ref.
+ */
+
+var toString = {}.toString;
+
+/**
+ * Return ETag for `body`.
+ *
+ * @param {String|Buffer} body
+ * @return {String}
+ * @api private
+ */
+
+exports.etag = function(body){
+ return '"' + crc32.signed(body) + '"';
+};
+
+/**
+ * Make `locals()` bound to the given `obj`.
+ *
+ * This is used for `app.locals` and `res.locals`.
+ *
+ * @param {Object} obj
+ * @return {Function}
+ * @api private
+ */
+
+exports.locals = function(obj){
+ function locals(obj){
+ for (var key in obj) locals[key] = obj[key];
+ return obj;
+ };
+
+ return locals;
+};
+
+/**
+ * Check if `path` looks absolute.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.isAbsolute = function(path){
+ if ('/' == path[0]) return true;
+ if (':' == path[1] && '\\' == path[2]) return true;
+};
+
+/**
+ * Flatten the given `arr`.
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @api private
+ */
+
+exports.flatten = function(arr, ret){
+ var ret = ret || []
+ , len = arr.length;
+ for (var i = 0; i < len; ++i) {
+ if (Array.isArray(arr[i])) {
+ exports.flatten(arr[i], ret);
+ } else {
+ ret.push(arr[i]);
+ }
+ }
+ return ret;
+};
+
+/**
+ * Normalize the given `type`, for example "html" becomes "text/html".
+ *
+ * @param {String} type
+ * @return {Object}
+ * @api private
+ */
+
+exports.normalizeType = function(type){
+ return ~type.indexOf('/')
+ ? acceptParams(type)
+ : { value: mime.lookup(type), params: {} };
+};
+
+/**
+ * Normalize `types`, for example "html" becomes "text/html".
+ *
+ * @param {Array} types
+ * @return {Array}
+ * @api private
+ */
+
+exports.normalizeTypes = function(types){
+ var ret = [];
+
+ for (var i = 0; i < types.length; ++i) {
+ ret.push(exports.normalizeType(types[i]));
+ }
+
+ return ret;
+};
+
+/**
+ * Return the acceptable type in `types`, if any.
+ *
+ * @param {Array} types
+ * @param {String} str
+ * @return {String}
+ * @api private
+ */
+
+exports.acceptsArray = function(types, str){
+ // accept anything when Accept is not present
+ if (!str) return types[0];
+
+ // parse
+ var accepted = exports.parseAccept(str)
+ , normalized = exports.normalizeTypes(types)
+ , len = accepted.length;
+
+ for (var i = 0; i < len; ++i) {
+ for (var j = 0, jlen = types.length; j < jlen; ++j) {
+ if (exports.accept(normalized[j], accepted[i])) {
+ return types[j];
+ }
+ }
+ }
+};
+
+/**
+ * Check if `type(s)` are acceptable based on
+ * the given `str`.
+ *
+ * @param {String|Array} type(s)
+ * @param {String} str
+ * @return {Boolean|String}
+ * @api private
+ */
+
+exports.accepts = function(type, str){
+ if ('string' == typeof type) type = type.split(/ *, */);
+ return exports.acceptsArray(type, str);
+};
+
+/**
+ * Check if `type` array is acceptable for `other`.
+ *
+ * @param {Object} type
+ * @param {Object} other
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.accept = function(type, other){
+ var t = type.value.split('/');
+ return (t[0] == other.type || '*' == other.type)
+ && (t[1] == other.subtype || '*' == other.subtype)
+ && paramsEqual(type.params, other.params);
+};
+
+/**
+ * Check if accept params are equal.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @return {Boolean}
+ * @api private
+ */
+
+function paramsEqual(a, b){
+ return !Object.keys(a).some(function(k) {
+ return a[k] != b[k];
+ });
+}
+
+/**
+ * Parse accept `str`, returning
+ * an array objects containing
+ * `.type` and `.subtype` along
+ * with the values provided by
+ * `parseQuality()`.
+ *
+ * @param {Type} name
+ * @return {Type}
+ * @api private
+ */
+
+exports.parseAccept = function(str){
+ return exports
+ .parseParams(str)
+ .map(function(obj){
+ var parts = obj.value.split('/');
+ obj.type = parts[0];
+ obj.subtype = parts[1];
+ return obj;
+ });
+};
+
+/**
+ * Parse quality `str`, returning an
+ * array of objects with `.value`,
+ * `.quality` and optional `.params`
+ *
+ * @param {String} str
+ * @return {Array}
+ * @api private
+ */
+
+exports.parseParams = function(str){
+ return str
+ .split(/ *, */)
+ .map(acceptParams)
+ .filter(function(obj){
+ return obj.quality;
+ })
+ .sort(function(a, b){
+ if (a.quality === b.quality) {
+ return a.originalIndex - b.originalIndex;
+ } else {
+ return b.quality - a.quality;
+ }
+ });
+};
+
+/**
+ * Parse accept params `str` returning an
+ * object with `.value`, `.quality` and `.params`.
+ * also includes `.originalIndex` for stable sorting
+ *
+ * @param {String} str
+ * @return {Object}
+ * @api private
+ */
+
+function acceptParams(str, index) {
+ var parts = str.split(/ *; */);
+ var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
+
+ for (var i = 1; i < parts.length; ++i) {
+ var pms = parts[i].split(/ *= */);
+ if ('q' == pms[0]) {
+ ret.quality = parseFloat(pms[1]);
+ } else {
+ ret.params[pms[0]] = pms[1];
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Escape special characters in the given string of html.
+ *
+ * @param {String} html
+ * @return {String}
+ * @api private
+ */
+
+exports.escape = function(html) {
+ return String(html)
+ .replace(/&/g, '&amp;')
+ .replace(/"/g, '&quot;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;');
+};
+
+/**
+ * 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|RegExp|Array} path
+ * @param {Array} keys
+ * @param {Boolean} sensitive
+ * @param {Boolean} strict
+ * @return {RegExp}
+ * @api private
+ */
+
+exports.pathRegexp = function(path, keys, sensitive, strict) {
+ if (toString.call(path) == '[object RegExp]') return path;
+ if (Array.isArray(path)) path = '(' + path.join('|') + ')';
+ path = path
+ .concat(strict ? '' : '/?')
+ .replace(/\/\(/g, '(?:/')
+ .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){
+ keys.push({ name: key, optional: !! optional });
+ slash = slash || '';
+ return ''
+ + (optional ? '' : slash)
+ + '(?:'
+ + (optional ? slash : '')
+ + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
+ + (optional || '')
+ + (star ? '(/*)?' : '');
+ })
+ .replace(/([\/.])/g, '\\$1')
+ .replace(/\*/g, '(.*)');
+ return new RegExp('^' + path + '$', sensitive ? '' : 'i');
+}
diff --git a/node_modules/express/lib/view.js b/node_modules/express/lib/view.js
new file mode 100644
index 0000000..ae20b17
--- /dev/null
+++ b/node_modules/express/lib/view.js
@@ -0,0 +1,76 @@
+/**
+ * Module dependencies.
+ */
+
+var path = require('path')
+ , fs = require('fs')
+ , utils = require('./utils')
+ , dirname = path.dirname
+ , basename = path.basename
+ , extname = path.extname
+ , exists = fs.existsSync || path.existsSync
+ , join = path.join;
+
+/**
+ * Expose `View`.
+ */
+
+module.exports = View;
+
+/**
+ * Initialize a new `View` with the given `name`.
+ *
+ * Options:
+ *
+ * - `defaultEngine` the default template engine name
+ * - `engines` template engine require() cache
+ * - `root` root path for view lookup
+ *
+ * @param {String} name
+ * @param {Object} options
+ * @api private
+ */
+
+function View(name, options) {
+ options = options || {};
+ this.name = name;
+ this.root = options.root;
+ var engines = options.engines;
+ this.defaultEngine = options.defaultEngine;
+ var ext = this.ext = extname(name);
+ if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine);
+ this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
+ this.path = this.lookup(name);
+}
+
+/**
+ * Lookup view by the given `path`
+ *
+ * @param {String} path
+ * @return {String}
+ * @api private
+ */
+
+View.prototype.lookup = function(path){
+ var ext = this.ext;
+
+ // <path>.<engine>
+ if (!utils.isAbsolute(path)) path = join(this.root, path);
+ if (exists(path)) return path;
+
+ // <path>/index.<engine>
+ path = join(dirname(path), basename(path, ext), 'index' + ext);
+ if (exists(path)) return path;
+};
+
+/**
+ * Render with the given `options` and callback `fn(err, str)`.
+ *
+ * @param {Object} options
+ * @param {Function} fn
+ * @api private
+ */
+
+View.prototype.render = function(options, fn){
+ this.engine(this.path, options, fn);
+};