mirror of
https://github.com/sstent/expressmongotest.git
synced 2026-01-29 02:21:49 +00:00
upgraded to express 3.x, converted jade templates, and worked out array notation for articles/exercises
This commit is contained in:
533
test/node_modules/express/lib/application.js
generated
vendored
Normal file
533
test/node_modules/express/lib/application.js
generated
vendored
Normal file
@@ -0,0 +1,533 @@
|
||||
/**
|
||||
* 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.viewCallbacks = [];
|
||||
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');
|
||||
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;
|
||||
});
|
||||
|
||||
// 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('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 seemlessly 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) {
|
||||
if (this.settings.hasOwnProperty(setting)) {
|
||||
return this.settings[setting];
|
||||
} else if (this.parent) {
|
||||
return this.parent.set(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 attacked 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 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);
|
||||
};
|
||||
105
test/node_modules/express/lib/express.js
generated
vendored
105
test/node_modules/express/lib/express.js
generated
vendored
@@ -1,77 +1,90 @@
|
||||
|
||||
/*!
|
||||
* Express
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var connect = require('connect')
|
||||
, HTTPSServer = require('./https')
|
||||
, HTTPServer = require('./http')
|
||||
, proto = require('./application')
|
||||
, Route = require('./router/route')
|
||||
, Router = require('./router')
|
||||
, req = require('./request')
|
||||
, res = require('./response')
|
||||
, utils = connect.utils;
|
||||
|
||||
/**
|
||||
* Re-export connect auto-loaders.
|
||||
*
|
||||
* This prevents the need to `require('connect')` in order
|
||||
* to access core middleware, so for example `express.logger()` instead
|
||||
* of `require('connect').logger()`.
|
||||
* Expose `createApplication()`.
|
||||
*/
|
||||
|
||||
var exports = module.exports = connect.middleware;
|
||||
exports = module.exports = createApplication;
|
||||
|
||||
/**
|
||||
* Framework version.
|
||||
*/
|
||||
|
||||
exports.version = '2.5.11';
|
||||
exports.version = '3.0.5';
|
||||
|
||||
/**
|
||||
* Shortcut for `new Server(...)`.
|
||||
* Expose mime.
|
||||
*/
|
||||
|
||||
exports.mime = connect.mime;
|
||||
|
||||
/**
|
||||
* Create an express application.
|
||||
*
|
||||
* @param {Function} ...
|
||||
* @return {Server}
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.createServer = function(options){
|
||||
if ('object' == typeof options) {
|
||||
return new HTTPSServer(options, Array.prototype.slice.call(arguments, 1));
|
||||
} else {
|
||||
return new HTTPServer(Array.prototype.slice.call(arguments));
|
||||
}
|
||||
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.HTTPServer = HTTPServer;
|
||||
exports.HTTPSServer = HTTPSServer;
|
||||
exports.Route = Route;
|
||||
|
||||
/**
|
||||
* View extensions.
|
||||
*/
|
||||
|
||||
exports.View =
|
||||
exports.view = require('./view');
|
||||
|
||||
/**
|
||||
* Response extensions.
|
||||
*/
|
||||
|
||||
require('./response');
|
||||
|
||||
/**
|
||||
* Request extensions.
|
||||
*/
|
||||
|
||||
require('./request');
|
||||
exports.Router = Router;
|
||||
|
||||
// Error handler title
|
||||
|
||||
|
||||
582
test/node_modules/express/lib/http.js
generated
vendored
582
test/node_modules/express/lib/http.js
generated
vendored
@@ -1,582 +0,0 @@
|
||||
/*!
|
||||
* Express - HTTPServer
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var qs = require('qs')
|
||||
, connect = require('connect')
|
||||
, router = require('./router')
|
||||
, Router = require('./router')
|
||||
, view = require('./view')
|
||||
, toArray = require('./utils').toArray
|
||||
, methods = router.methods.concat('del', 'all')
|
||||
, url = require('url')
|
||||
, utils = connect.utils;
|
||||
|
||||
/**
|
||||
* Expose `HTTPServer`.
|
||||
*/
|
||||
|
||||
exports = module.exports = HTTPServer;
|
||||
|
||||
/**
|
||||
* Server proto.
|
||||
*/
|
||||
|
||||
var app = HTTPServer.prototype;
|
||||
|
||||
/**
|
||||
* Initialize a new `HTTPServer` with optional `middleware`.
|
||||
*
|
||||
* @param {Array} middleware
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function HTTPServer(middleware){
|
||||
connect.HTTPServer.call(this, []);
|
||||
this.init(middleware);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherit from `connect.HTTPServer`.
|
||||
*/
|
||||
|
||||
app.__proto__ = connect.HTTPServer.prototype;
|
||||
|
||||
/**
|
||||
* Initialize the server.
|
||||
*
|
||||
* @param {Array} middleware
|
||||
* @api private
|
||||
*/
|
||||
|
||||
app.init = function(middleware){
|
||||
var self = this;
|
||||
this.cache = {};
|
||||
this.settings = {};
|
||||
this.redirects = {};
|
||||
this.isCallbacks = {};
|
||||
this._locals = {};
|
||||
this.dynamicViewHelpers = {};
|
||||
this.errorHandlers = [];
|
||||
|
||||
this.set('env', process.env.NODE_ENV || 'development');
|
||||
|
||||
// expose objects to each other
|
||||
this.use(function(req, res, next){
|
||||
req.query = req.query || {};
|
||||
res.setHeader('X-Powered-By', 'Express');
|
||||
req.app = res.app = self;
|
||||
req.res = res;
|
||||
res.req = req;
|
||||
req.next = next;
|
||||
// assign req.query
|
||||
if (req.url.indexOf('?') > 0) {
|
||||
var query = url.parse(req.url).query;
|
||||
req.query = qs.parse(query);
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
// apply middleware
|
||||
if (middleware) middleware.forEach(self.use.bind(self));
|
||||
|
||||
// router
|
||||
this.routes = new Router(this);
|
||||
this.__defineGetter__('router', function(){
|
||||
this.__usedRouter = true;
|
||||
return self.routes.middleware;
|
||||
});
|
||||
|
||||
// default locals
|
||||
this.locals({
|
||||
settings: this.settings
|
||||
, app: this
|
||||
});
|
||||
|
||||
// default development configuration
|
||||
this.configure('development', function(){
|
||||
this.enable('hints');
|
||||
});
|
||||
|
||||
// default production configuration
|
||||
this.configure('production', function(){
|
||||
this.enable('view cache');
|
||||
});
|
||||
|
||||
// register error handlers on "listening"
|
||||
// so that they disregard definition position.
|
||||
this.on('listening', this.registerErrorHandlers.bind(this));
|
||||
|
||||
// route manipulation methods
|
||||
methods.forEach(function(method){
|
||||
self.lookup[method] = function(path){
|
||||
return self.routes.lookup(method, path);
|
||||
};
|
||||
|
||||
self.match[method] = function(path){
|
||||
return self.routes.match(method, path);
|
||||
};
|
||||
|
||||
self.remove[method] = function(path){
|
||||
return self.routes.lookup(method, path).remove();
|
||||
};
|
||||
});
|
||||
|
||||
// del -> delete
|
||||
self.lookup.del = self.lookup.delete;
|
||||
self.match.del = self.match.delete;
|
||||
self.remove.del = self.remove.delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove routes matching the given `path`.
|
||||
*
|
||||
* @param {Route} path
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.remove = function(path){
|
||||
return this.routes.lookup('all', path).remove();
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup routes defined with a path
|
||||
* equivalent to `path`.
|
||||
*
|
||||
* @param {Stirng} path
|
||||
* @return {Array}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.lookup = function(path){
|
||||
return this.routes.lookup('all', path);
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup routes matching the given `url`.
|
||||
*
|
||||
* @param {Stirng} url
|
||||
* @return {Array}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.match = function(url){
|
||||
return this.routes.match('all', url);
|
||||
};
|
||||
|
||||
/**
|
||||
* When using the vhost() middleware register error handlers.
|
||||
*/
|
||||
|
||||
app.onvhost = function(){
|
||||
this.registerErrorHandlers();
|
||||
};
|
||||
|
||||
/**
|
||||
* Register error handlers.
|
||||
*
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.registerErrorHandlers = function(){
|
||||
this.errorHandlers.forEach(function(fn){
|
||||
this.use(function(err, req, res, next){
|
||||
fn.apply(this, arguments);
|
||||
});
|
||||
}, this);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Proxy `connect.HTTPServer#use()` to apply settings to
|
||||
* mounted applications.
|
||||
*
|
||||
* @param {String|Function|Server} route
|
||||
* @param {Function|Server} middleware
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.use = function(route, middleware){
|
||||
var app, base, handle;
|
||||
|
||||
if ('string' != typeof route) {
|
||||
middleware = route, route = '/';
|
||||
}
|
||||
|
||||
// express app
|
||||
if (middleware.handle && middleware.set) app = middleware;
|
||||
|
||||
// restore .app property on req and res
|
||||
if (app) {
|
||||
app.route = route;
|
||||
middleware = function(req, res, next) {
|
||||
var orig = req.app;
|
||||
app.handle(req, res, function(err){
|
||||
req.app = res.app = orig;
|
||||
next(err);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
connect.HTTPServer.prototype.use.call(this, route, middleware);
|
||||
|
||||
// mounted an app, invoke the hook
|
||||
// and adjust some settings
|
||||
if (app) {
|
||||
base = this.set('basepath') || this.route;
|
||||
if ('/' == base) base = '';
|
||||
base = base + (app.set('basepath') || app.route);
|
||||
app.set('basepath', base);
|
||||
app.parent = this;
|
||||
if (app.__mounted) app.__mounted.call(app, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign a callback `fn` which is called
|
||||
* when this `Server` is passed to `Server#use()`.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* var app = express.createServer()
|
||||
* , blog = express.createServer();
|
||||
*
|
||||
* blog.mounted(function(parent){
|
||||
* // parent is app
|
||||
* // "this" is blog
|
||||
* });
|
||||
*
|
||||
* app.use(blog);
|
||||
*
|
||||
* @param {Function} fn
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.mounted = function(fn){
|
||||
this.__mounted = fn;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* See: view.register.
|
||||
*
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.register = function(){
|
||||
view.register.apply(this, arguments);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register the given view helpers `obj`. This method
|
||||
* can be called several times to apply additional helpers.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.helpers =
|
||||
app.locals = function(obj){
|
||||
utils.merge(this._locals, obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register the given dynamic view helpers `obj`. This method
|
||||
* can be called several times to apply additional helpers.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.dynamicHelpers = function(obj){
|
||||
utils.merge(this.dynamicViewHelpers, obj);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Map the given param placeholder `name`(s) to the given callback(s).
|
||||
*
|
||||
* Param mapping is used to provide pre-conditions to routes
|
||||
* which us normalized placeholders. This callback has the same
|
||||
* signature as regular middleware, for example below when ":userId"
|
||||
* is used this function will be invoked in an attempt to load the user.
|
||||
*
|
||||
* app.param('userId', 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'));
|
||||
* }
|
||||
* });
|
||||
* });
|
||||
*
|
||||
* Passing a single function allows you to map logic
|
||||
* to the values passed to `app.param()`, for example
|
||||
* this is useful to provide coercion support in a concise manner.
|
||||
*
|
||||
* The following example maps regular expressions to param values
|
||||
* ensuring that they match, otherwise passing control to the next
|
||||
* route:
|
||||
*
|
||||
* app.param(function(name, regexp){
|
||||
* if (regexp instanceof RegExp) {
|
||||
* return function(req, res, next, val){
|
||||
* var captures;
|
||||
* if (captures = regexp.exec(String(val))) {
|
||||
* req.params[name] = captures;
|
||||
* next();
|
||||
* } else {
|
||||
* next('route');
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* We can now use it as shown below, where "/commit/:commit" expects
|
||||
* that the value for ":commit" is at 5 or more digits. The capture
|
||||
* groups are then available as `req.params.commit` as we defined
|
||||
* in the function above.
|
||||
*
|
||||
* app.param('commit', /^\d{5,}$/);
|
||||
*
|
||||
* For more of this useful functionality take a look
|
||||
* at [express-params](http://github.com/visionmedia/express-params).
|
||||
*
|
||||
* @param {String|Array|Function} name
|
||||
* @param {Function} fn
|
||||
* @return {Server} 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.routes.param(name);
|
||||
// single
|
||||
} else {
|
||||
if (':' == name[0]) name = name.substr(1);
|
||||
fns.forEach(function(fn){
|
||||
self.routes.param(name, fn);
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign a custom exception handler callback `fn`.
|
||||
* These handlers are always _last_ in the middleware stack.
|
||||
*
|
||||
* @param {Function} fn
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.error = function(fn){
|
||||
this.errorHandlers.push(fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register the given callback `fn` for the given `type`.
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {Function} fn
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.is = function(type, fn){
|
||||
if (!fn) return this.isCallbacks[type];
|
||||
this.isCallbacks[type] = fn;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign `setting` to `val`, or return `setting`'s value.
|
||||
* Mounted servers inherit their parent server's settings.
|
||||
*
|
||||
* @param {String} setting
|
||||
* @param {String} val
|
||||
* @return {Server|Mixed} for chaining, or the setting value
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.set = function(setting, val){
|
||||
if (val === undefined) {
|
||||
if (this.settings.hasOwnProperty(setting)) {
|
||||
return this.settings[setting];
|
||||
} else if (this.parent) {
|
||||
return this.parent.set(setting);
|
||||
}
|
||||
} else {
|
||||
this.settings[setting] = val;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if `setting` is enabled.
|
||||
*
|
||||
* @param {String} setting
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.enabled = function(setting){
|
||||
return !!this.set(setting);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if `setting` is disabled.
|
||||
*
|
||||
* @param {String} setting
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.disabled = function(setting){
|
||||
return !this.set(setting);
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable `setting`.
|
||||
*
|
||||
* @param {String} setting
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.enable = function(setting){
|
||||
return this.set(setting, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Disable `setting`.
|
||||
*
|
||||
* @param {String} setting
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.disable = function(setting){
|
||||
return this.set(setting, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Redirect `key` to `url`.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {String} url
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.redirect = function(key, url){
|
||||
this.redirects[key] = url;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* });
|
||||
*
|
||||
* @param {String} env...
|
||||
* @param {Function} fn
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.configure = function(env, fn){
|
||||
var envs = 'all'
|
||||
, args = toArray(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 `.route(VERB, ...)`.
|
||||
*/
|
||||
|
||||
methods.forEach(function(method){
|
||||
app[method] = function(path){
|
||||
if (1 == arguments.length) return this.routes.lookup(method, path);
|
||||
var args = [method].concat(toArray(arguments));
|
||||
if (!this.__usedRouter) this.use(this.router);
|
||||
return this.routes._route.apply(this.routes, args);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Special-cased "all" method, applying the given route `path`,
|
||||
* middleware, and callback to _every_ HTTP method.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Function} ...
|
||||
* @return {Server} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
app.all = function(path){
|
||||
var args = arguments;
|
||||
if (1 == args.length) return this.routes.lookup('all', path);
|
||||
methods.forEach(function(method){
|
||||
if ('all' == method || 'del' == method) return;
|
||||
app[method].apply(this, args);
|
||||
}, this);
|
||||
return this;
|
||||
};
|
||||
|
||||
// del -> delete alias
|
||||
|
||||
app.del = app.delete;
|
||||
|
||||
52
test/node_modules/express/lib/https.js
generated
vendored
52
test/node_modules/express/lib/https.js
generated
vendored
@@ -1,52 +0,0 @@
|
||||
|
||||
/*!
|
||||
* Express - HTTPSServer
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var connect = require('connect')
|
||||
, HTTPServer = require('./http')
|
||||
, https = require('https');
|
||||
|
||||
/**
|
||||
* Expose `HTTPSServer`.
|
||||
*/
|
||||
|
||||
exports = module.exports = HTTPSServer;
|
||||
|
||||
/**
|
||||
* Server proto.
|
||||
*/
|
||||
|
||||
var app = HTTPSServer.prototype;
|
||||
|
||||
/**
|
||||
* Initialize a new `HTTPSServer` with the
|
||||
* given `options`, and optional `middleware`.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Array} middleware
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function HTTPSServer(options, middleware){
|
||||
connect.HTTPSServer.call(this, options, []);
|
||||
this.init(middleware);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inherit from `connect.HTTPSServer`.
|
||||
*/
|
||||
|
||||
app.__proto__ = connect.HTTPSServer.prototype;
|
||||
|
||||
// mixin HTTPServer methods
|
||||
|
||||
Object.keys(HTTPServer.prototype).forEach(function(method){
|
||||
app[method] = HTTPServer.prototype[method];
|
||||
});
|
||||
33
test/node_modules/express/lib/middleware.js
generated
vendored
Normal file
33
test/node_modules/express/lib/middleware.js
generated
vendored
Normal file
@@ -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.settings['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();
|
||||
}
|
||||
};
|
||||
553
test/node_modules/express/lib/request.js
generated
vendored
553
test/node_modules/express/lib/request.js
generated
vendored
@@ -1,168 +1,248 @@
|
||||
|
||||
/*!
|
||||
* Express - request
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var http = require('http')
|
||||
, req = http.IncomingMessage.prototype
|
||||
, utils = require('./utils')
|
||||
, parse = require('url').parse
|
||||
, mime = require('mime');
|
||||
, connect = require('connect')
|
||||
, fresh = require('fresh')
|
||||
, parseRange = require('range-parser')
|
||||
, parse = connect.utils.parseUrl
|
||||
, mime = connect.mime;
|
||||
|
||||
/**
|
||||
* Default flash formatters.
|
||||
*
|
||||
* @type Object
|
||||
* Request prototype.
|
||||
*/
|
||||
|
||||
var flashFormatters = exports.flashFormatters = {
|
||||
s: function(val){
|
||||
return String(val);
|
||||
}
|
||||
var req = exports = module.exports = {
|
||||
__proto__: http.IncomingMessage.prototype
|
||||
};
|
||||
|
||||
/**
|
||||
* Return request header or optional default.
|
||||
* Return request header.
|
||||
*
|
||||
* The `Referrer` header field is special-cased,
|
||||
* both `Referrer` and `Referer` will yield are
|
||||
* interchangeable.
|
||||
* both `Referrer` and `Referer` are interchangeable.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* req.header('Content-Type');
|
||||
* req.get('Content-Type');
|
||||
* // => "text/plain"
|
||||
*
|
||||
* req.header('content-type');
|
||||
* req.get('content-type');
|
||||
* // => "text/plain"
|
||||
*
|
||||
* req.header('Accept');
|
||||
* req.get('Something');
|
||||
* // => undefined
|
||||
*
|
||||
* req.header('Accept', 'text/html');
|
||||
* // => "text/html"
|
||||
*
|
||||
* Aliased as `req.header()`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {String} defaultValue
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.header = function(name, defaultValue){
|
||||
req.get =
|
||||
req.header = function(name){
|
||||
switch (name = name.toLowerCase()) {
|
||||
case 'referer':
|
||||
case 'referrer':
|
||||
return this.headers.referrer
|
||||
|| this.headers.referer
|
||||
|| defaultValue;
|
||||
|| this.headers.referer;
|
||||
default:
|
||||
return this.headers[name] || defaultValue;
|
||||
return this.headers[name];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get `field`'s `param` value, defaulting to ''.
|
||||
* 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".
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* req.get('content-disposition', 'filename');
|
||||
* // => "something.png"
|
||||
*
|
||||
* @param {String} field
|
||||
* @param {String} param
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.get = function(field, param){
|
||||
var val = this.header(field);
|
||||
if (!val) return '';
|
||||
var regexp = new RegExp(param + ' *= *(?:"([^"]+)"|([^;]+))', 'i');
|
||||
if (!regexp.exec(val)) return '';
|
||||
return RegExp.$1 || RegExp.$2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Short-hand for `require('url').parse(req.url).pathname`.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('path', function(){
|
||||
return parse(this.url).pathname;
|
||||
});
|
||||
|
||||
/**
|
||||
* Check if the _Accept_ header is present, and includes the given `type`.
|
||||
*
|
||||
* When the _Accept_ header is not present `true` is returned. Otherwise
|
||||
* the given `type` is matched by an exact match, and then subtypes. You
|
||||
* may pass the subtype such as "html" which is then converted internally
|
||||
* to "text/html" using the mime lookup table.
|
||||
* 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');
|
||||
* // => true
|
||||
* // => "html"
|
||||
*
|
||||
* // Accept: text/*; application/json
|
||||
* // Accept: text/*, application/json
|
||||
* req.accepts('html');
|
||||
* // => "html"
|
||||
* req.accepts('text/html');
|
||||
* req.accepts('text/plain');
|
||||
* // => "text/html"
|
||||
* req.accepts('json, text');
|
||||
* // => "json"
|
||||
* req.accepts('application/json');
|
||||
* // => true
|
||||
* // => "application/json"
|
||||
*
|
||||
* // Accept: text/*, application/json
|
||||
* req.accepts('image/png');
|
||||
* req.accepts('png');
|
||||
* // => false
|
||||
* // => undefined
|
||||
*
|
||||
* @param {String} type
|
||||
* @return {Boolean}
|
||||
* // 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){
|
||||
var accept = this.header('Accept');
|
||||
|
||||
// normalize extensions ".json" -> "json"
|
||||
if (type && '.' == type[0]) type = type.substr(1);
|
||||
|
||||
// when Accept does not exist, or contains '*/*' return true
|
||||
if (!accept || ~accept.indexOf('*/*')) {
|
||||
return true;
|
||||
} else if (type) {
|
||||
// allow "html" vs "text/html" etc
|
||||
if (!~type.indexOf('/')) type = mime.lookup(type);
|
||||
|
||||
// check if we have a direct match
|
||||
if (~accept.indexOf(type)) return true;
|
||||
|
||||
// check if we have type/*
|
||||
type = type.split('/')[0] + '/*';
|
||||
return !!~accept.indexOf(type);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return utils.accepts(type, this.get('Accept'));
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 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
|
||||
.parseQuality(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
|
||||
.parseQuality(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
|
||||
* - Checks urlencoded body params, ex: id=12
|
||||
*
|
||||
* To utilize urlencoded request bodies, `req.body`
|
||||
* To utilize request bodies, `req.body`
|
||||
* should be an object. This can be done by using
|
||||
* the `connect.bodyParser` middleware.
|
||||
* the `connect.bodyParser()` middleware.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Mixed} defaultValue
|
||||
@@ -171,80 +251,15 @@ req.accepts = function(type){
|
||||
*/
|
||||
|
||||
req.param = function(name, defaultValue){
|
||||
// route params like /user/:id
|
||||
if (this.params && this.params.hasOwnProperty(name) && undefined !== this.params[name]) {
|
||||
return this.params[name];
|
||||
}
|
||||
// query string params
|
||||
if (undefined !== this.query[name]) {
|
||||
return this.query[name];
|
||||
}
|
||||
// request body params via connect.bodyParser
|
||||
if (this.body && undefined !== this.body[name]) {
|
||||
return this.body[name];
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Queue flash `msg` of the given `type`.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* req.flash('info', 'email sent');
|
||||
* req.flash('error', 'email delivery failed');
|
||||
* req.flash('info', 'email re-sent');
|
||||
* // => 2
|
||||
*
|
||||
* req.flash('info');
|
||||
* // => ['email sent', 'email re-sent']
|
||||
*
|
||||
* req.flash('info');
|
||||
* // => []
|
||||
*
|
||||
* req.flash();
|
||||
* // => { error: ['email delivery failed'], info: [] }
|
||||
*
|
||||
* Formatting:
|
||||
*
|
||||
* Flash notifications also support arbitrary formatting support.
|
||||
* For example you may pass variable arguments to `req.flash()`
|
||||
* and use the %s specifier to be replaced by the associated argument:
|
||||
*
|
||||
* req.flash('info', 'email has been sent to %s.', userName);
|
||||
*
|
||||
* To add custom formatters use the `exports.flashFormatters` object.
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {String} msg
|
||||
* @return {Array|Object|Number}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.flash = function(type, msg){
|
||||
if (this.session === undefined) throw Error('req.flash() requires sessions');
|
||||
var msgs = this.session.flash = this.session.flash || {};
|
||||
if (type && msg) {
|
||||
var i = 2
|
||||
, args = arguments
|
||||
, formatters = this.app.flashFormatters || {};
|
||||
formatters.__proto__ = flashFormatters;
|
||||
msg = utils.miniMarkdown(msg);
|
||||
msg = msg.replace(/%([a-zA-Z])/g, function(_, format){
|
||||
var formatter = formatters[format];
|
||||
if (formatter) return formatter(utils.escape(args[i++]));
|
||||
});
|
||||
return (msgs[type] = msgs[type] || []).push(msg);
|
||||
} else if (type) {
|
||||
var arr = msgs[type];
|
||||
delete msgs[type];
|
||||
return arr || [];
|
||||
} else {
|
||||
this.session.flash = {};
|
||||
return msgs;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the incoming request contains the "Content-Type"
|
||||
* header field, and it contains the give mime `type`.
|
||||
@@ -254,45 +269,25 @@ req.flash = function(type, msg){
|
||||
* // 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
|
||||
*
|
||||
* Ad-hoc callbacks can also be registered with Express, to perform
|
||||
* assertions again the request, for example if we need an expressive
|
||||
* way to check if our incoming request is an image, we can register "an image"
|
||||
* callback:
|
||||
*
|
||||
* app.is('an image', function(req){
|
||||
* return 0 == req.headers['content-type'].indexOf('image');
|
||||
* });
|
||||
*
|
||||
* Now within our route callbacks, we can use to to assert content types
|
||||
* such as "image/jpeg", "image/png", etc.
|
||||
*
|
||||
* app.post('/image/upload', function(req, res, next){
|
||||
* if (req.is('an image')) {
|
||||
* // do something
|
||||
* } else {
|
||||
* next();
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @param {String} type
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.is = function(type){
|
||||
var fn = this.app.is(type);
|
||||
if (fn) return fn(this);
|
||||
var ct = this.headers['content-type'];
|
||||
var ct = this.get('Content-Type');
|
||||
if (!ct) return false;
|
||||
ct = ct.split(';')[0];
|
||||
if (!~type.indexOf('/')) type = mime.lookup(type);
|
||||
@@ -306,22 +301,6 @@ req.is = function(type){
|
||||
return !! ~ct.indexOf(type);
|
||||
};
|
||||
|
||||
// Callback for isXMLHttpRequest / xhr
|
||||
|
||||
function isxhr() {
|
||||
return this.header('X-Requested-With', '').toLowerCase() === 'xmlhttprequest';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the request was an _XMLHttpRequest_.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('isXMLHttpRequest', isxhr);
|
||||
req.__defineGetter__('xhr', isxhr);
|
||||
|
||||
/**
|
||||
* Return the protocol string "http" or "https"
|
||||
* when requested with TLS. When the "trust proxy"
|
||||
@@ -335,11 +314,11 @@ req.__defineGetter__('xhr', isxhr);
|
||||
*/
|
||||
|
||||
req.__defineGetter__('protocol', function(){
|
||||
var trustProxy = this.app.set('trust proxy');
|
||||
var trustProxy = this.app.get('trust proxy');
|
||||
return this.connection.encrypted
|
||||
? 'https'
|
||||
: trustProxy
|
||||
? (this.header('X-Forwarded-Proto') || 'http')
|
||||
? (this.get('X-Forwarded-Proto') || 'http')
|
||||
: 'http';
|
||||
});
|
||||
|
||||
@@ -354,4 +333,154 @@ req.__defineGetter__('protocol', function(){
|
||||
|
||||
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().split(':');
|
||||
return { username: auth[0], password: auth[1] };
|
||||
});
|
||||
|
||||
/**
|
||||
* Return subdomains as an array.
|
||||
*
|
||||
* For example "tobi.ferrets.example.com"
|
||||
* would provide `["ferrets", "tobi"]`.
|
||||
*
|
||||
* @return {Array}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
req.__defineGetter__('subdomains', function(){
|
||||
return this.get('Host')
|
||||
.split('.')
|
||||
.slice(0, -2)
|
||||
.reverse();
|
||||
});
|
||||
|
||||
/**
|
||||
* 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(){
|
||||
return this.get('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();
|
||||
});
|
||||
|
||||
853
test/node_modules/express/lib/response.js
generated
vendored
853
test/node_modules/express/lib/response.js
generated
vendored
@@ -1,145 +1,29 @@
|
||||
|
||||
/*!
|
||||
* Express - response
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var fs = require('fs')
|
||||
, http = require('http')
|
||||
var http = require('http')
|
||||
, path = require('path')
|
||||
, connect = require('connect')
|
||||
, utils = connect.utils
|
||||
, parseRange = require('./utils').parseRange
|
||||
, res = http.ServerResponse.prototype
|
||||
, send = connect.static.send
|
||||
, mime = require('mime')
|
||||
, 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;
|
||||
|
||||
/**
|
||||
* Send a response with the given `body` and optional `headers` and `status` code.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* res.send();
|
||||
* res.send(new Buffer('wahoo'));
|
||||
* res.send({ some: 'json' });
|
||||
* res.send('<p>some html</p>');
|
||||
* res.send('Sorry, cant find that', 404);
|
||||
* res.send('text', { 'Content-Type': 'text/plain' }, 201);
|
||||
* res.send(404);
|
||||
*
|
||||
* @param {String|Object|Number|Buffer} body or status
|
||||
* @param {Object|Number} headers or status
|
||||
* @param {Number} status
|
||||
* @return {ServerResponse}
|
||||
* @api public
|
||||
* Response prototype.
|
||||
*/
|
||||
|
||||
res.send = function(body, headers, status){
|
||||
// allow status as second arg
|
||||
if ('number' == typeof headers) {
|
||||
status = headers,
|
||||
headers = null;
|
||||
}
|
||||
|
||||
// default status
|
||||
status = status || this.statusCode;
|
||||
|
||||
// allow 0 args as 204
|
||||
if (!arguments.length || undefined === body) status = 204;
|
||||
|
||||
// determine content type
|
||||
switch (typeof body) {
|
||||
case 'number':
|
||||
if (!this.header('Content-Type')) {
|
||||
this.contentType('.txt');
|
||||
}
|
||||
body = http.STATUS_CODES[status = body];
|
||||
break;
|
||||
case 'string':
|
||||
if (!this.header('Content-Type')) {
|
||||
this.charset = this.charset || 'utf-8';
|
||||
this.contentType('.html');
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
case 'object':
|
||||
if (Buffer.isBuffer(body)) {
|
||||
if (!this.header('Content-Type')) {
|
||||
this.contentType('.bin');
|
||||
}
|
||||
} else {
|
||||
return this.json(body, headers, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// populate Content-Length
|
||||
if (undefined !== body && !this.header('Content-Length')) {
|
||||
this.header('Content-Length', Buffer.isBuffer(body)
|
||||
? body.length
|
||||
: Buffer.byteLength(body));
|
||||
}
|
||||
|
||||
// merge headers passed
|
||||
if (headers) {
|
||||
var fields = Object.keys(headers);
|
||||
for (var i = 0, len = fields.length; i < len; ++i) {
|
||||
var field = fields[i];
|
||||
this.header(field, headers[field]);
|
||||
}
|
||||
}
|
||||
|
||||
// strip irrelevant headers
|
||||
if (204 == status || 304 == status) {
|
||||
this.removeHeader('Content-Type');
|
||||
this.removeHeader('Content-Length');
|
||||
body = '';
|
||||
}
|
||||
|
||||
// respond
|
||||
this.statusCode = status;
|
||||
this.end('HEAD' == this.req.method ? null : body);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send JSON response with `obj`, optional `headers`, and optional `status`.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* res.json(null);
|
||||
* res.json({ user: 'tj' });
|
||||
* res.json('oh noes!', 500);
|
||||
* res.json('I dont have that', 404);
|
||||
*
|
||||
* @param {Mixed} obj
|
||||
* @param {Object|Number} headers or status
|
||||
* @param {Number} status
|
||||
* @return {ServerResponse}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.json = function(obj, headers, status){
|
||||
var body = JSON.stringify(obj)
|
||||
, callback = this.req.query.callback
|
||||
, jsonp = this.app.enabled('jsonp callback');
|
||||
|
||||
this.charset = this.charset || 'utf-8';
|
||||
this.header('Content-Type', 'application/json');
|
||||
|
||||
if (callback && jsonp) {
|
||||
this.header('Content-Type', 'text/javascript');
|
||||
body = callback.replace(/[^\w$.]/g, '') + '(' + body + ');';
|
||||
}
|
||||
|
||||
return this.send(body, headers, status);
|
||||
var res = module.exports = {
|
||||
__proto__: http.ServerResponse.prototype
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -156,15 +40,242 @@ res.status = function(code){
|
||||
};
|
||||
|
||||
/**
|
||||
* Transfer the file at the given `path`. Automatically sets
|
||||
* the _Content-Type_ response header field. `next()` is called
|
||||
* when `path` is a directory, or when an error occurs.
|
||||
* 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
|
||||
@@ -172,8 +283,11 @@ res.status = function(code){
|
||||
*/
|
||||
|
||||
res.sendfile = function(path, options, fn){
|
||||
var next = this.req.next;
|
||||
options = options || {};
|
||||
var self = this
|
||||
, req = self.req
|
||||
, next = this.req.next
|
||||
, options = options || {}
|
||||
, done;
|
||||
|
||||
// support function as second arg
|
||||
if ('function' == typeof options) {
|
||||
@@ -181,32 +295,185 @@ res.sendfile = function(path, options, fn){
|
||||
options = {};
|
||||
}
|
||||
|
||||
options.path = encodeURIComponent(path);
|
||||
options.callback = fn;
|
||||
send(this.req, this, next, 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);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set _Content-Type_ response header passed through `mime.lookup()`.
|
||||
* Transfer the file at the given `path` as an attachment.
|
||||
*
|
||||
* Examples:
|
||||
* 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.
|
||||
*
|
||||
* var filename = 'path/to/image.png';
|
||||
* res.contentType(filename);
|
||||
* // res.headers['Content-Type'] is now "image/png"
|
||||
* This method uses `res.sendfile()`.
|
||||
*
|
||||
* res.contentType('.html');
|
||||
* res.contentType('html');
|
||||
* res.contentType('json');
|
||||
* res.contentType('png');
|
||||
*
|
||||
* @param {String} type
|
||||
* @return {String} the resolved mime type
|
||||
* @param {String} path
|
||||
* @param {String|Function} filename or fn
|
||||
* @param {Function} fn
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.contentType = function(type){
|
||||
return this.header('Content-Type', mime.lookup(type));
|
||||
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));
|
||||
obj[key](req, this, next);
|
||||
} else if (fn) {
|
||||
fn();
|
||||
} else {
|
||||
var err = new Error('Not Acceptable');
|
||||
err.status = 406;
|
||||
err.types = normalizeTypes(keys);
|
||||
next(err);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -218,81 +485,67 @@ res.contentType = function(type){
|
||||
*/
|
||||
|
||||
res.attachment = function(filename){
|
||||
if (filename) this.contentType(filename);
|
||||
this.header('Content-Disposition', filename
|
||||
if (filename) this.type(extname(filename));
|
||||
this.set('Content-Disposition', filename
|
||||
? 'attachment; filename="' + basename(filename) + '"'
|
||||
: 'attachment');
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transfer the file at the given `path`, with optional
|
||||
* `filename` as an attachment and optional callback `fn(err)`,
|
||||
* and optional `fn2(err)` which is invoked when an error has
|
||||
* occurred after header has been sent.
|
||||
* Set header `field` to `val`, or pass
|
||||
* an object of header fields.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {String|Function} filename or fn
|
||||
* @param {Function} fn
|
||||
* @param {Function} fn2
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.download = function(path, filename, fn, fn2){
|
||||
var self = this;
|
||||
|
||||
// support callback as second arg
|
||||
if ('function' == typeof filename) {
|
||||
fn2 = fn;
|
||||
fn = filename;
|
||||
filename = null;
|
||||
}
|
||||
|
||||
// transfer the file
|
||||
this.attachment(filename || path).sendfile(path, function(err){
|
||||
var sentHeader = self._header;
|
||||
if (err) {
|
||||
if (!sentHeader) self.removeHeader('Content-Disposition');
|
||||
if (sentHeader) {
|
||||
fn2 && fn2(err);
|
||||
} else if (fn) {
|
||||
fn(err);
|
||||
} else {
|
||||
self.req.next(err);
|
||||
}
|
||||
} else if (fn) {
|
||||
fn();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Set or get response header `name` with optional `val`.
|
||||
* Examples:
|
||||
*
|
||||
* @param {String} name
|
||||
* res.set('Accept', 'application/json');
|
||||
* res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
|
||||
*
|
||||
* Aliased as `res.header()`.
|
||||
*
|
||||
* @param {String|Object} field
|
||||
* @param {String} val
|
||||
* @return {ServerResponse} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.header = function(name, val){
|
||||
if (1 == arguments.length) return this.getHeader(name);
|
||||
this.setHeader(name, val);
|
||||
res.set =
|
||||
res.header = function(field, val){
|
||||
if (2 == arguments.length) {
|
||||
this.setHeader(field, '' + val);
|
||||
} else {
|
||||
for (var key in field) {
|
||||
this.setHeader(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) };
|
||||
this.cookie(name, '', options
|
||||
? utils.merge(options, opts)
|
||||
var opts = { expires: new Date(1), path: '/' };
|
||||
return this.cookie(name, '', options
|
||||
? utils.merge(opts, options)
|
||||
: opts);
|
||||
};
|
||||
|
||||
@@ -302,7 +555,8 @@ res.clearCookie = function(name, options){
|
||||
* Options:
|
||||
*
|
||||
* - `maxAge` max-age in milliseconds, converted to `expires`
|
||||
* - `path` defaults to the "basepath" setting which is typically "/"
|
||||
* - `signed` sign the cookie
|
||||
* - `path` defaults to "/"
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
@@ -313,147 +567,156 @@ res.clearCookie = function(name, options){
|
||||
* res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {String} val
|
||||
* @param {String|Object} val
|
||||
* @param {Options} options
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.cookie = function(name, val, options){
|
||||
options = options || {};
|
||||
if ('maxAge' in options) options.expires = new Date(Date.now() + options.maxAge);
|
||||
if (undefined === options.path) options.path = this.app.set('basepath');
|
||||
var cookie = utils.serializeCookie(name, val, options);
|
||||
this.header('Set-Cookie', cookie);
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Redirect to the given `url` with optional response `status`
|
||||
* defauling to 302.
|
||||
* defaulting to 302.
|
||||
*
|
||||
* 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 the application's
|
||||
* "basepath" setting. Express also supports "basepath" out of the box,
|
||||
* which can be set via `app.set('basepath', '/blog');`, and defaults
|
||||
* to '/'.
|
||||
* to the _Referrer_ or _Referer_ headers or "/".
|
||||
*
|
||||
* Redirect Mapping:
|
||||
*
|
||||
* To extend the redirect mapping capabilities that Express provides,
|
||||
* we may use the `app.redirect()` method:
|
||||
*
|
||||
* app.redirect('google', 'http://google.com');
|
||||
*
|
||||
* Now in a route we may call:
|
||||
* Examples:
|
||||
*
|
||||
* res.redirect('google');
|
||||
* 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
|
||||
*
|
||||
* We may also map dynamic redirects:
|
||||
* Mounting:
|
||||
*
|
||||
* app.redirect('comments', function(req, res){
|
||||
* return '/post/' + req.params.id + '/comments';
|
||||
* });
|
||||
* When an application is mounted, and `res.redirect()`
|
||||
* is given a path that does _not_ lead with "/". For
|
||||
* example suppose a "blog" app is mounted at "/blog",
|
||||
* the following redirect would result in "/blog/login":
|
||||
*
|
||||
* So now we may do the following, and the redirect will dynamically adjust to
|
||||
* the context of the request. If we called this route with _GET /post/12_ our
|
||||
* redirect _Location_ would be _/post/12/comments_.
|
||||
* res.redirect('login');
|
||||
*
|
||||
* app.get('/post/:id', function(req, res){
|
||||
* res.redirect('comments');
|
||||
* });
|
||||
* While the leading slash would result in a redirect to "/login":
|
||||
*
|
||||
* Unless an absolute `url` is given, the app's mount-point
|
||||
* will be respected. For example if we redirect to `/posts`,
|
||||
* and our app is mounted at `/blog` we will redirect to `/blog/posts`.
|
||||
* res.redirect('/login');
|
||||
*
|
||||
* @param {String} url
|
||||
* @param {Number} code
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.redirect = function(url, status){
|
||||
res.redirect = function(url){
|
||||
var app = this.app
|
||||
, req = this.req
|
||||
, base = app.set('basepath') || app.route
|
||||
, status = status || 302
|
||||
, head = 'HEAD' == req.method
|
||||
, status = 302
|
||||
, body;
|
||||
|
||||
// Setup redirect map
|
||||
var map = {
|
||||
back: req.header('Referrer', base)
|
||||
, home: base
|
||||
};
|
||||
// allow status / url
|
||||
if (2 == arguments.length) {
|
||||
if ('number' == typeof url) {
|
||||
status = url;
|
||||
url = arguments[1];
|
||||
} else {
|
||||
status = arguments[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Support custom redirect map
|
||||
map.__proto__ = app.redirects;
|
||||
// setup redirect map
|
||||
var map = { back: req.get('Referrer') || '/' };
|
||||
|
||||
// Attempt mapped redirect
|
||||
var mapped = 'function' == typeof map[url]
|
||||
? map[url](req, this)
|
||||
: map[url];
|
||||
// perform redirect
|
||||
url = map[url] || url;
|
||||
|
||||
// Perform redirect
|
||||
url = mapped || url;
|
||||
// relative
|
||||
if (!~url.indexOf('://') && 0 != url.indexOf('//')) {
|
||||
var path = app.path();
|
||||
|
||||
// Relative
|
||||
if (!~url.indexOf('://')) {
|
||||
// Respect mount-point
|
||||
if ('/' != base && 0 != url.indexOf(base)) url = base + url;
|
||||
|
||||
// Absolute
|
||||
var host = req.headers.host;
|
||||
url = req.protocol + '://' + host + url;
|
||||
// relative to path
|
||||
if ('.' == url[0]) {
|
||||
url = req.path + '/' + url;
|
||||
// relative to mount-point
|
||||
} else if ('/' != url[0]) {
|
||||
url = path + '/' + url;
|
||||
}
|
||||
}
|
||||
|
||||
// Support text/{plain,html} by default
|
||||
if (req.accepts('html')) {
|
||||
body = '<p>' + http.STATUS_CODES[status] + '. Redirecting to <a href="' + url + '">' + url + '</a></p>';
|
||||
this.header('Content-Type', 'text/html');
|
||||
} else {
|
||||
body = http.STATUS_CODES[status] + '. Redirecting to ' + url;
|
||||
this.header('Content-Type', 'text/plain');
|
||||
}
|
||||
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.header('Location', url);
|
||||
this.set('Location', url);
|
||||
this.set('Content-Length', Buffer.byteLength(body));
|
||||
this.end(head ? null : body);
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign the view local variable `name` to `val` or return the
|
||||
* local previously assigned to `name`.
|
||||
* 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.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Mixed} val
|
||||
* @return {Mixed} val
|
||||
* 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.local = function(name, val){
|
||||
this._locals = this._locals || {};
|
||||
return undefined === val
|
||||
? this._locals[name]
|
||||
: this._locals[name] = val;
|
||||
};
|
||||
res.render = function(view, options, fn){
|
||||
var self = this
|
||||
, options = options || {}
|
||||
, req = this.req
|
||||
, app = req.app;
|
||||
|
||||
/**
|
||||
* Assign several locals with the given `obj`,
|
||||
* or return the locals.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @return {Object|Undefined}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.locals =
|
||||
res.helpers = function(obj){
|
||||
if (obj) {
|
||||
for (var key in obj) {
|
||||
this.local(key, obj[key]);
|
||||
}
|
||||
} else {
|
||||
return this._locals;
|
||||
// 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);
|
||||
};
|
||||
|
||||
53
test/node_modules/express/lib/router/collection.js
generated
vendored
53
test/node_modules/express/lib/router/collection.js
generated
vendored
@@ -1,53 +0,0 @@
|
||||
|
||||
/*!
|
||||
* Express - router - Collection
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Expose `Collection`.
|
||||
*/
|
||||
|
||||
module.exports = Collection;
|
||||
|
||||
/**
|
||||
* Initialize a new route `Collection`
|
||||
* with the given `router`.
|
||||
*
|
||||
* @param {Router} router
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function Collection(router) {
|
||||
Array.apply(this, arguments);
|
||||
this.router = router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from `Array.prototype`.
|
||||
*/
|
||||
|
||||
Collection.prototype.__proto__ = Array.prototype;
|
||||
|
||||
/**
|
||||
* Remove the routes in this collection.
|
||||
*
|
||||
* @return {Collection} of routes removed
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Collection.prototype.remove = function(){
|
||||
var router = this.router
|
||||
, len = this.length
|
||||
, ret = new Collection(this.router);
|
||||
|
||||
for (var i = 0; i < len; ++i) {
|
||||
if (router.remove(this[i])) {
|
||||
ret.push(this[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
275
test/node_modules/express/lib/router/index.js
generated
vendored
275
test/node_modules/express/lib/router/index.js
generated
vendored
@@ -1,19 +1,12 @@
|
||||
|
||||
/*!
|
||||
* Express - Router
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var Route = require('./route')
|
||||
, Collection = require('./collection')
|
||||
, utils = require('../utils')
|
||||
, parse = require('url').parse
|
||||
, toArray = utils.toArray;
|
||||
, methods = require('methods')
|
||||
, debug = require('debug')('express:router')
|
||||
, parse = require('connect').utils.parseUrl;
|
||||
|
||||
/**
|
||||
* Expose `Router` constructor.
|
||||
@@ -22,26 +15,21 @@ var Route = require('./route')
|
||||
exports = module.exports = Router;
|
||||
|
||||
/**
|
||||
* Expose HTTP methods.
|
||||
*/
|
||||
|
||||
var methods = exports.methods = require('./methods');
|
||||
|
||||
/**
|
||||
* Initialize a new `Router` with the given `app`.
|
||||
*
|
||||
* @param {express.HTTPServer} app
|
||||
* Initialize a new `Router` with the given `options`.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function Router(app) {
|
||||
function Router(options) {
|
||||
options = options || {};
|
||||
var self = this;
|
||||
this.app = app;
|
||||
this.routes = {};
|
||||
this.map = {};
|
||||
this.params = {};
|
||||
this._params = [];
|
||||
|
||||
this.middleware = function(req, res, next){
|
||||
this.caseSensitive = options.caseSensitive;
|
||||
this.strict = options.strict;
|
||||
this.middleware = function router(req, res, next){
|
||||
self._dispatch(req, res, next);
|
||||
};
|
||||
}
|
||||
@@ -83,104 +71,6 @@ Router.prototype.param = function(name, fn){
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a `Collection` of all routes defined.
|
||||
*
|
||||
* @return {Collection}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Router.prototype.all = function(){
|
||||
return this.find(function(){
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the given `route`, returns
|
||||
* a bool indicating if the route was present
|
||||
* or not.
|
||||
*
|
||||
* @param {Route} route
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Router.prototype.remove = function(route){
|
||||
var routes = this.routes[route.method]
|
||||
, len = routes.length;
|
||||
|
||||
for (var i = 0; i < len; ++i) {
|
||||
if (route == routes[i]) {
|
||||
routes.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return routes with route paths matching `path`.
|
||||
*
|
||||
* @param {String} method
|
||||
* @param {String} path
|
||||
* @return {Collection}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Router.prototype.lookup = function(method, path){
|
||||
return this.find(function(route){
|
||||
return path == route.path
|
||||
&& (route.method == method
|
||||
|| method == 'all');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Return routes with regexps that match the given `url`.
|
||||
*
|
||||
* @param {String} method
|
||||
* @param {String} url
|
||||
* @return {Collection}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Router.prototype.match = function(method, url){
|
||||
return this.find(function(route){
|
||||
return route.match(url)
|
||||
&& (route.method == method
|
||||
|| method == 'all');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Find routes based on the return value of `fn`
|
||||
* which is invoked once per route.
|
||||
*
|
||||
* @param {Function} fn
|
||||
* @return {Collection}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Router.prototype.find = function(fn){
|
||||
var len = methods.length
|
||||
, ret = new Collection(this)
|
||||
, method
|
||||
, routes
|
||||
, route;
|
||||
|
||||
for (var i = 0; i < len; ++i) {
|
||||
method = methods[i];
|
||||
routes = this.routes[method];
|
||||
if (!routes) continue;
|
||||
for (var j = 0, jlen = routes.length; j < jlen; ++j) {
|
||||
route = routes[j];
|
||||
if (fn(route)) ret.push(route);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Route dispatcher aka the route "middleware".
|
||||
*
|
||||
@@ -194,6 +84,8 @@ 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
|
||||
@@ -201,8 +93,7 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
, paramVal
|
||||
, route
|
||||
, keys
|
||||
, key
|
||||
, ret;
|
||||
, key;
|
||||
|
||||
// match next route
|
||||
function nextRoute(err) {
|
||||
@@ -210,13 +101,11 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
}
|
||||
|
||||
// match route
|
||||
req.route = route = self._match(req, i);
|
||||
|
||||
// implied OPTIONS
|
||||
if (!route && 'OPTIONS' == req.method) return self._options(req, res);
|
||||
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
|
||||
@@ -251,7 +140,7 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
};
|
||||
|
||||
param(err);
|
||||
|
||||
|
||||
// single param callbacks
|
||||
function paramCallback(err) {
|
||||
var fn = paramCallbacks[paramIndex++];
|
||||
@@ -269,7 +158,8 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
if (fn.length < 4) return callbacks(err);
|
||||
fn(err, req, res, callbacks);
|
||||
} else if (fn) {
|
||||
fn(req, res, callbacks);
|
||||
if (fn.length < 4) return fn(req, res, callbacks);
|
||||
callbacks();
|
||||
} else {
|
||||
nextRoute(err);
|
||||
}
|
||||
@@ -280,44 +170,10 @@ Router.prototype._dispatch = function(req, res, next){
|
||||
})(0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Respond to __OPTIONS__ method.
|
||||
*
|
||||
* @param {IncomingMessage} req
|
||||
* @param {ServerResponse} res
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Router.prototype._options = function(req, res){
|
||||
var path = parse(req.url).pathname
|
||||
, body = this._optionsFor(path).join(',');
|
||||
res.send(body, { Allow: body });
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an array of HTTP verbs or "options" for `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Array}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Router.prototype._optionsFor = function(path){
|
||||
var self = this;
|
||||
return methods.filter(function(method){
|
||||
var routes = self.routes[method];
|
||||
if (!routes || 'options' == method) return;
|
||||
for (var i = 0, len = routes.length; i < len; ++i) {
|
||||
if (routes[i].match(path)) return true;
|
||||
}
|
||||
}).map(function(method){
|
||||
return method.toUpperCase();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to match a route for `req`
|
||||
* starting from offset `i`.
|
||||
* with optional starting index of `i`
|
||||
* defaulting to 0.
|
||||
*
|
||||
* @param {IncomingMessage} req
|
||||
* @param {Number} i
|
||||
@@ -325,17 +181,20 @@ Router.prototype._optionsFor = function(path){
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Router.prototype._match = function(req, i){
|
||||
Router.prototype.matchRequest = function(req, i, head){
|
||||
var method = req.method.toLowerCase()
|
||||
, url = parse(req.url)
|
||||
, url = parse(req)
|
||||
, path = url.pathname
|
||||
, routes = this.routes
|
||||
, captures
|
||||
, route
|
||||
, keys;
|
||||
, routes = this.map
|
||||
, i = i || 0
|
||||
, route;
|
||||
|
||||
// pass HEAD to GET routes
|
||||
if ('head' == method) method = 'get';
|
||||
// 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]) {
|
||||
@@ -343,24 +202,7 @@ Router.prototype._match = function(req, i){
|
||||
// matching routes
|
||||
for (var len = routes.length; i < len; ++i) {
|
||||
route = routes[i];
|
||||
if (captures = route.match(path)) {
|
||||
keys = route.keys;
|
||||
route.params = [];
|
||||
|
||||
// params from capture groups
|
||||
for (var j = 1, jlen = captures.length; j < jlen; ++j) {
|
||||
var key = keys[j-1]
|
||||
, val = 'string' == typeof captures[j]
|
||||
? decodeURIComponent(captures[j])
|
||||
: captures[j];
|
||||
if (key) {
|
||||
route.params[key.name] = val;
|
||||
} else {
|
||||
route.params.push(val);
|
||||
}
|
||||
}
|
||||
|
||||
// all done
|
||||
if (route.match(path)) {
|
||||
req._route_index = i;
|
||||
return route;
|
||||
}
|
||||
@@ -368,6 +210,23 @@ Router.prototype._match = function(req, i){
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -378,21 +237,37 @@ Router.prototype._match = function(req, i){
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Router.prototype._route = function(method, path, callbacks){
|
||||
var app = this.app
|
||||
, callbacks = utils.flatten(toArray(arguments, 2));
|
||||
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('app.' + method + '() requires a path');
|
||||
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: app.enabled('case sensitive routes')
|
||||
, strict: app.enabled('strict routing')
|
||||
sensitive: this.caseSensitive,
|
||||
strict: this.strict
|
||||
});
|
||||
|
||||
// add it
|
||||
(this.routes[method] = this.routes[method] || [])
|
||||
.push(route);
|
||||
(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;
|
||||
};
|
||||
});
|
||||
|
||||
79
test/node_modules/express/lib/router/methods.js
generated
vendored
79
test/node_modules/express/lib/router/methods.js
generated
vendored
@@ -1,79 +0,0 @@
|
||||
|
||||
/*!
|
||||
* Express - router - methods
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Hypertext Transfer Protocol -- HTTP/1.1
|
||||
* http://www.ietf.org/rfc/rfc2616.txt
|
||||
*/
|
||||
|
||||
var RFC2616 = ['OPTIONS', 'GET', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT'];
|
||||
|
||||
/**
|
||||
* HTTP Extensions for Distributed Authoring -- WEBDAV
|
||||
* http://www.ietf.org/rfc/rfc2518.txt
|
||||
*/
|
||||
|
||||
var RFC2518 = ['PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK'];
|
||||
|
||||
/**
|
||||
* Versioning Extensions to WebDAV
|
||||
* http://www.ietf.org/rfc/rfc3253.txt
|
||||
*/
|
||||
|
||||
var RFC3253 = ['VERSION-CONTROL', 'REPORT', 'CHECKOUT', 'CHECKIN', 'UNCHECKOUT', 'MKWORKSPACE', 'UPDATE', 'LABEL', 'MERGE', 'BASELINE-CONTROL', 'MKACTIVITY'];
|
||||
|
||||
/**
|
||||
* Ordered Collections Protocol (WebDAV)
|
||||
* http://www.ietf.org/rfc/rfc3648.txt
|
||||
*/
|
||||
|
||||
var RFC3648 = ['ORDERPATCH'];
|
||||
|
||||
/**
|
||||
* Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol
|
||||
* http://www.ietf.org/rfc/rfc3744.txt
|
||||
*/
|
||||
|
||||
var RFC3744 = ['ACL'];
|
||||
|
||||
/**
|
||||
* Web Distributed Authoring and Versioning (WebDAV) SEARCH
|
||||
* http://www.ietf.org/rfc/rfc5323.txt
|
||||
*/
|
||||
|
||||
var RFC5323 = ['SEARCH'];
|
||||
|
||||
/**
|
||||
* PATCH Method for HTTP
|
||||
* http://www.ietf.org/rfc/rfc5789.txt
|
||||
*/
|
||||
|
||||
var RFC5789 = ['PATCH'];
|
||||
|
||||
/**
|
||||
* PURGE Method for caching reverse-proxy
|
||||
* http://wiki.squid-cache.org/SquidFaq/OperatingSquid#How_can_I_purge_an_object_from_my_cache.3F
|
||||
* https://www.varnish-cache.org/docs/trunk/tutorial/purging.html
|
||||
*/
|
||||
|
||||
var CACHE_PURGE = ['PURGE'];
|
||||
|
||||
/**
|
||||
* Expose the methods.
|
||||
*/
|
||||
|
||||
module.exports = [].concat(
|
||||
RFC2616
|
||||
, RFC2518
|
||||
, RFC3253
|
||||
, RFC3648
|
||||
, RFC3744
|
||||
, RFC5323
|
||||
, RFC5789
|
||||
, CACHE_PURGE).map(function(method){
|
||||
return method.toLowerCase();
|
||||
});
|
||||
74
test/node_modules/express/lib/router/route.js
generated
vendored
74
test/node_modules/express/lib/router/route.js
generated
vendored
@@ -1,10 +1,10 @@
|
||||
|
||||
/*!
|
||||
* Express - router - Route
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var utils = require('../utils');
|
||||
|
||||
/**
|
||||
* Expose `Route`.
|
||||
*/
|
||||
@@ -32,57 +32,41 @@ function Route(method, path, callbacks, options) {
|
||||
this.path = path;
|
||||
this.method = method;
|
||||
this.callbacks = callbacks;
|
||||
this.regexp = normalize(path
|
||||
this.regexp = utils.pathRegexp(path
|
||||
, this.keys = []
|
||||
, options.sensitive
|
||||
, options.strict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this route matches `path` and return captures made.
|
||||
* Check if this route matches `path`, if so
|
||||
* populate `.params`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Array}
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Route.prototype.match = function(path){
|
||||
return this.regexp.exec(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;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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} path
|
||||
* @param {Array} keys
|
||||
* @param {Boolean} sensitive
|
||||
* @param {Boolean} strict
|
||||
* @return {RegExp}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function normalize(path, keys, sensitive, strict) {
|
||||
if (path instanceof RegExp) return path;
|
||||
path = path
|
||||
.concat(strict ? '' : '/?')
|
||||
.replace(/\/\(/g, '(?:/')
|
||||
.replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?/g, function(_, slash, format, key, capture, optional){
|
||||
keys.push({ name: key, optional: !! optional });
|
||||
slash = slash || '';
|
||||
return ''
|
||||
+ (optional ? '' : slash)
|
||||
+ '(?:'
|
||||
+ (optional ? slash : '')
|
||||
+ (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
|
||||
+ (optional || '');
|
||||
})
|
||||
.replace(/([\/.])/g, '\\$1')
|
||||
.replace(/\*/g, '(.*)');
|
||||
return new RegExp('^' + path + '$', sensitive ? '' : 'i');
|
||||
}
|
||||
|
||||
298
test/node_modules/express/lib/utils.js
generated
vendored
298
test/node_modules/express/lib/utils.js
generated
vendored
@@ -1,10 +1,44 @@
|
||||
|
||||
/*!
|
||||
* Express - Utils
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var mime = require('connect').mime
|
||||
, crc32 = require('buffer-crc32');
|
||||
|
||||
/**
|
||||
* 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){
|
||||
obj.viewCallbacks = obj.viewCallbacks || [];
|
||||
|
||||
function locals(obj){
|
||||
for (var key in obj) locals[key] = obj[key];
|
||||
return obj;
|
||||
};
|
||||
|
||||
return locals;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if `path` looks absolute.
|
||||
*
|
||||
@@ -18,31 +52,6 @@ exports.isAbsolute = function(path){
|
||||
if (':' == path[1] && '\\' == path[2]) return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Merge object `b` with `a` giving precedence to
|
||||
* values in object `a`.
|
||||
*
|
||||
* @param {Object} a
|
||||
* @param {Object} b
|
||||
* @return {Object} a
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.union = function(a, b){
|
||||
if (a && b) {
|
||||
var keys = Object.keys(b)
|
||||
, len = keys.length
|
||||
, key;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
key = keys[i];
|
||||
if (!a.hasOwnProperty(key)) {
|
||||
a[key] = b[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
};
|
||||
|
||||
/**
|
||||
* Flatten the given `arr`.
|
||||
*
|
||||
@@ -65,26 +74,158 @@ exports.flatten = function(arr, ret){
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse mini markdown implementation.
|
||||
* The following conversions are supported,
|
||||
* primarily for the "flash" middleware:
|
||||
* Normalize the given `type`, for example "html" becomes "text/html".
|
||||
*
|
||||
* _foo_ or *foo* become <em>foo</em>
|
||||
* __foo__ or **foo** become <strong>foo</strong>
|
||||
* [A](B) becomes <a href="B">A</a>
|
||||
* @param {String} type
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.normalizeType = function(type){
|
||||
return ~type.indexOf('/') ? type : mime.lookup(type);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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(~types[i].indexOf('/')
|
||||
? types[i]
|
||||
: mime.lookup(types[i]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the acceptable type in `types`, if any.
|
||||
*
|
||||
* @param {Array} types
|
||||
* @param {String} str
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.miniMarkdown = function(str){
|
||||
return String(str)
|
||||
.replace(/(__|\*\*)(.*?)\1/g, '<strong>$2</strong>')
|
||||
.replace(/(_|\*)(.*?)\1/g, '<em>$2</em>')
|
||||
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
|
||||
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].split('/'), 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 {Array} type
|
||||
* @param {Object} other
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.accept = function(type, other){
|
||||
return (type[0] == other.type || '*' == other.type)
|
||||
&& (type[1] == other.subtype || '*' == other.subtype);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
.parseQuality(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` and
|
||||
* `.quality`.
|
||||
*
|
||||
* @param {Type} name
|
||||
* @return {Type}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.parseQuality = function(str){
|
||||
return str
|
||||
.split(/ *, */)
|
||||
.map(quality)
|
||||
.filter(function(obj){
|
||||
return obj.quality;
|
||||
})
|
||||
.sort(function(a, b){
|
||||
return b.quality - a.quality;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse quality `str` returning an
|
||||
* object with `.value` and `.quality`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function quality(str) {
|
||||
var parts = str.split(/ *; */)
|
||||
, val = parts[0];
|
||||
|
||||
var q = parts[1]
|
||||
? parseFloat(parts[1].split(/ *= */)[1])
|
||||
: 1;
|
||||
|
||||
return { value: val, quality: q };
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape special characters in the given string of html.
|
||||
*
|
||||
@@ -102,51 +243,40 @@ exports.escape = function(html) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse "Range" header `str` relative to the given file `size`.
|
||||
* Normalize the given path string,
|
||||
* returning a regular expression.
|
||||
*
|
||||
* @param {Number} size
|
||||
* @param {String} str
|
||||
* @return {Array}
|
||||
* 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.parseRange = function(size, str){
|
||||
var valid = true;
|
||||
var arr = str.substr(6).split(',').map(function(range){
|
||||
var range = range.split('-')
|
||||
, start = parseInt(range[0], 10)
|
||||
, end = parseInt(range[1], 10);
|
||||
|
||||
// -500
|
||||
if (isNaN(start)) {
|
||||
start = size - end;
|
||||
end = size - 1;
|
||||
// 500-
|
||||
} else if (isNaN(end)) {
|
||||
end = size - 1;
|
||||
}
|
||||
|
||||
// Invalid
|
||||
if (isNaN(start) || isNaN(end) || start > end) valid = false;
|
||||
|
||||
return { start: start, end: end };
|
||||
});
|
||||
return valid ? arr : undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast alternative to `Array.prototype.slice.call()`.
|
||||
*
|
||||
* @param {Arguments} args
|
||||
* @param {Number} n
|
||||
* @return {Array}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.toArray = function(args, i){
|
||||
var arr = []
|
||||
, len = args.length
|
||||
, i = i || 0;
|
||||
for (; i < len; ++i) arr.push(args[i]);
|
||||
return arr;
|
||||
};
|
||||
exports.pathRegexp = function(path, keys, sensitive, strict) {
|
||||
if (path instanceof 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');
|
||||
}
|
||||
480
test/node_modules/express/lib/view.js
generated
vendored
480
test/node_modules/express/lib/view.js
generated
vendored
@@ -1,460 +1,76 @@
|
||||
|
||||
/*!
|
||||
* Express - view
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var path = require('path')
|
||||
, extname = path.extname
|
||||
, fs = require('fs')
|
||||
, utils = require('./utils')
|
||||
, dirname = path.dirname
|
||||
, basename = path.basename
|
||||
, utils = require('connect').utils
|
||||
, View = require('./view/view')
|
||||
, partial = require('./view/partial')
|
||||
, union = require('./utils').union
|
||||
, merge = utils.merge
|
||||
, http = require('http')
|
||||
, res = http.ServerResponse.prototype;
|
||||
, extname = path.extname
|
||||
, exists = fs.existsSync || path.existsSync
|
||||
, join = path.join;
|
||||
|
||||
/**
|
||||
* Expose constructors.
|
||||
* Expose `View`.
|
||||
*/
|
||||
|
||||
exports = module.exports = View;
|
||||
module.exports = View;
|
||||
|
||||
/**
|
||||
* Export template engine registrar.
|
||||
*/
|
||||
|
||||
exports.register = View.register;
|
||||
|
||||
/**
|
||||
* Lookup and compile `view` with cache support by supplying
|
||||
* both the `cache` object and `cid` string,
|
||||
* followed by `options` passed to `exports.lookup()`.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object} cache
|
||||
* @param {Object} cid
|
||||
* @param {Object} options
|
||||
* @return {View}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.compile = function(view, cache, cid, options){
|
||||
if (cache && cid && cache[cid]){
|
||||
options.filename = cache[cid].path;
|
||||
return cache[cid];
|
||||
}
|
||||
|
||||
// lookup
|
||||
view = exports.lookup(view, options);
|
||||
|
||||
// hints
|
||||
if (!view.exists) {
|
||||
if (options.hint) hintAtViewPaths(view.original, options);
|
||||
var err = new Error('failed to locate view "' + view.original.view + '"');
|
||||
err.view = view.original;
|
||||
throw err;
|
||||
}
|
||||
|
||||
// compile
|
||||
options.filename = view.path;
|
||||
view.fn = view.templateEngine.compile(view.contents, options);
|
||||
cache[cid] = view;
|
||||
|
||||
return view;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup `view`, returning an instanceof `View`.
|
||||
* Initialize a new `View` with the given `name`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `root` root directory path
|
||||
* - `defaultEngine` default template engine
|
||||
* - `parentView` parent `View` object
|
||||
* - `cache` cache object
|
||||
* - `cacheid` optional cache id
|
||||
* - `defaultEngine` the default template engine name
|
||||
* - `engines` template engine require() cache
|
||||
* - `root` root path for view lookup
|
||||
*
|
||||
* Lookup:
|
||||
*
|
||||
* - partial `_<name>`
|
||||
* - any `<name>/index`
|
||||
* - non-layout `../<name>/index`
|
||||
* - any `<root>/<name>`
|
||||
* - partial `<root>/_<name>`
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {String} name
|
||||
* @param {Object} options
|
||||
* @return {View}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.lookup = function(view, options){
|
||||
var orig = view = new View(view, options)
|
||||
, partial = options.isPartial
|
||||
, layout = options.isLayout;
|
||||
|
||||
// Try _ prefix ex: ./views/_<name>.jade
|
||||
// taking precedence over the direct path
|
||||
if (partial) {
|
||||
view = new View(orig.prefixPath, options);
|
||||
if (!view.exists) view = orig;
|
||||
}
|
||||
|
||||
// Try index ex: ./views/user/index.jade
|
||||
if (!layout && !view.exists) view = new View(orig.indexPath, options);
|
||||
|
||||
// Try ../<name>/index ex: ../user/index.jade
|
||||
// when calling partial('user') within the same dir
|
||||
if (!layout && !view.exists) view = new View(orig.upIndexPath, options);
|
||||
|
||||
// Try root ex: <root>/user.jade
|
||||
if (!view.exists) view = new View(orig.rootPath, options);
|
||||
|
||||
// Try root _ prefix ex: <root>/_user.jade
|
||||
if (!view.exists && partial) view = new View(view.prefixPath, options);
|
||||
|
||||
view.original = orig;
|
||||
return view;
|
||||
};
|
||||
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);
|
||||
this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express);
|
||||
this.path = this.lookup(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial render helper.
|
||||
* Lookup view by the given `path`
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function renderPartial(res, view, options, parentLocals, parent){
|
||||
var collection, object, locals;
|
||||
|
||||
if (options) {
|
||||
// collection
|
||||
if (options.collection) {
|
||||
collection = options.collection;
|
||||
delete options.collection;
|
||||
} else if ('length' in options) {
|
||||
collection = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
// locals
|
||||
if (options.locals) {
|
||||
locals = options.locals;
|
||||
delete options.locals;
|
||||
}
|
||||
|
||||
// object
|
||||
if ('Object' != options.constructor.name) {
|
||||
object = options;
|
||||
options = {};
|
||||
} else if (undefined != options.object) {
|
||||
object = options.object;
|
||||
delete options.object;
|
||||
}
|
||||
} else {
|
||||
options = {};
|
||||
}
|
||||
|
||||
// Inherit locals from parent
|
||||
union(options, parentLocals);
|
||||
|
||||
// Merge locals
|
||||
if (locals) merge(options, locals);
|
||||
|
||||
// Partials dont need layouts
|
||||
options.isPartial = true;
|
||||
options.layout = false;
|
||||
|
||||
// Deduce name from view path
|
||||
var name = options.as || partial.resolveObjectName(view);
|
||||
|
||||
// Render partial
|
||||
function render(){
|
||||
if (object) {
|
||||
if ('string' == typeof name) {
|
||||
options[name] = object;
|
||||
} else if (name === global) {
|
||||
merge(options, object);
|
||||
}
|
||||
}
|
||||
return res.render(view, options, null, parent, true);
|
||||
}
|
||||
|
||||
// Collection support
|
||||
if (collection) {
|
||||
var len = collection.length
|
||||
, buf = ''
|
||||
, keys
|
||||
, key
|
||||
, val;
|
||||
|
||||
options.collectionLength = len;
|
||||
|
||||
if ('number' == typeof len || Array.isArray(collection)) {
|
||||
for (var i = 0; i < len; ++i) {
|
||||
val = collection[i];
|
||||
options.firstInCollection = i == 0;
|
||||
options.indexInCollection = i;
|
||||
options.lastInCollection = i == len - 1;
|
||||
object = val;
|
||||
buf += render();
|
||||
}
|
||||
} else {
|
||||
keys = Object.keys(collection);
|
||||
len = keys.length;
|
||||
options.collectionLength = len;
|
||||
options.collectionKeys = keys;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
key = keys[i];
|
||||
val = collection[key];
|
||||
options.keyInCollection = key;
|
||||
options.firstInCollection = i == 0;
|
||||
options.indexInCollection = i;
|
||||
options.lastInCollection = i == len - 1;
|
||||
object = val;
|
||||
buf += render();
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
} else {
|
||||
return render();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render `view` partial with the given `options`. Optionally a
|
||||
* callback `fn(err, str)` may be passed instead of writing to
|
||||
* the socket.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `object` Single object with name derived from the view (unless `as` is present)
|
||||
*
|
||||
* - `as` Variable name for each `collection` value, defaults to the view name.
|
||||
* * as: 'something' will add the `something` local variable
|
||||
* * as: this will use the collection value as the template context
|
||||
* * as: global will merge the collection value's properties with `locals`
|
||||
*
|
||||
* - `collection` Array of objects, the name is derived from the view name itself.
|
||||
* For example _video.html_ will have a object _video_ available to it.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object|Array|Function} options, collection, callback, or object
|
||||
* @param {Function} fn
|
||||
* @param {String} path
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.partial = function(view, options, fn){
|
||||
var app = this.app
|
||||
, options = options || {}
|
||||
, viewEngine = app.set('view engine')
|
||||
, parent = {};
|
||||
|
||||
// accept callback as second argument
|
||||
if ('function' == typeof options) {
|
||||
fn = options;
|
||||
options = {};
|
||||
}
|
||||
|
||||
// root "views" option
|
||||
parent.dirname = app.set('views') || process.cwd() + '/views';
|
||||
|
||||
// utilize "view engine" option
|
||||
if (viewEngine) parent.engine = viewEngine;
|
||||
|
||||
// render the partial
|
||||
try {
|
||||
var str = renderPartial(this, view, options, null, parent);
|
||||
} catch (err) {
|
||||
if (fn) {
|
||||
fn(err);
|
||||
} else {
|
||||
this.req.next(err);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// callback or transfer
|
||||
if (fn) {
|
||||
fn(null, str);
|
||||
} else {
|
||||
this.send(str);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render `view` with the given `options` and optional callback `fn`.
|
||||
* When a callback function is given a response will _not_ be made
|
||||
* automatically, however otherwise a response of _200_ and _text/html_ is given.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `scope` Template evaluation context (the value of `this`)
|
||||
* - `debug` Output debugging information
|
||||
* - `status` Response status code
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object|Function} options or callback function
|
||||
* @param {Function} fn
|
||||
* @api public
|
||||
*/
|
||||
|
||||
res.render = function(view, opts, fn, parent, sub){
|
||||
// support callback function as second arg
|
||||
if ('function' == typeof opts) {
|
||||
fn = opts, opts = null;
|
||||
}
|
||||
|
||||
try {
|
||||
return this._render(view, opts, fn, parent, sub);
|
||||
} catch (err) {
|
||||
// callback given
|
||||
if (fn) {
|
||||
fn(err);
|
||||
// unwind to root call to prevent multiple callbacks
|
||||
} else if (sub) {
|
||||
throw err;
|
||||
// root template, next(err)
|
||||
} else {
|
||||
this.req.next(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// private render()
|
||||
|
||||
res._render = function(view, opts, fn, parent, sub){
|
||||
var options = {}
|
||||
, self = this
|
||||
, app = this.app
|
||||
, helpers = app._locals
|
||||
, dynamicHelpers = app.dynamicViewHelpers
|
||||
, viewOptions = app.set('view options')
|
||||
, root = app.set('views') || process.cwd() + '/views';
|
||||
|
||||
// cache id
|
||||
var cid = app.enabled('view cache')
|
||||
? view + (parent ? ':' + parent.path : '')
|
||||
: false;
|
||||
|
||||
// merge "view options"
|
||||
if (viewOptions) merge(options, viewOptions);
|
||||
|
||||
// merge res._locals
|
||||
if (this._locals) merge(options, this._locals);
|
||||
|
||||
// merge render() options
|
||||
if (opts) merge(options, opts);
|
||||
|
||||
// merge render() .locals
|
||||
if (opts && opts.locals) merge(options, opts.locals);
|
||||
|
||||
// status support
|
||||
if (options.status) this.statusCode = options.status;
|
||||
|
||||
// capture attempts
|
||||
options.attempts = [];
|
||||
|
||||
var partial = options.isPartial
|
||||
, layout = options.layout;
|
||||
|
||||
// Layout support
|
||||
if (true === layout || undefined === layout) {
|
||||
layout = 'layout';
|
||||
}
|
||||
|
||||
// Default execution scope to a plain object
|
||||
options.scope = options.scope || {};
|
||||
|
||||
// Populate view
|
||||
options.parentView = parent;
|
||||
|
||||
// "views" setting
|
||||
options.root = root;
|
||||
|
||||
// "view engine" setting
|
||||
options.defaultEngine = app.set('view engine');
|
||||
|
||||
// charset option
|
||||
if (options.charset) this.charset = options.charset;
|
||||
|
||||
// Dynamic helper support
|
||||
if (false !== options.dynamicHelpers) {
|
||||
// cache
|
||||
if (!this.__dynamicHelpers) {
|
||||
this.__dynamicHelpers = {};
|
||||
for (var key in dynamicHelpers) {
|
||||
this.__dynamicHelpers[key] = dynamicHelpers[key].call(
|
||||
this.app
|
||||
, this.req
|
||||
, this);
|
||||
}
|
||||
}
|
||||
|
||||
// apply
|
||||
merge(options, this.__dynamicHelpers);
|
||||
}
|
||||
|
||||
// Merge view helpers
|
||||
union(options, helpers);
|
||||
|
||||
// Always expose partial() as a local
|
||||
options.partial = function(path, opts){
|
||||
return renderPartial(self, path, opts, options, view);
|
||||
};
|
||||
|
||||
// View lookup
|
||||
options.hint = app.enabled('hints');
|
||||
view = exports.compile(view, app.cache, cid, options);
|
||||
|
||||
// layout helper
|
||||
options.layout = function(path){
|
||||
layout = path;
|
||||
};
|
||||
|
||||
// render
|
||||
var str = view.fn.call(options.scope, options);
|
||||
|
||||
// layout expected
|
||||
if (layout) {
|
||||
options.isLayout = true;
|
||||
options.layout = false;
|
||||
options.body = str;
|
||||
this.render(layout, options, fn, view, true);
|
||||
// partial return
|
||||
} else if (partial) {
|
||||
return str;
|
||||
// render complete, and
|
||||
// callback given
|
||||
} else if (fn) {
|
||||
fn(null, str);
|
||||
// respond
|
||||
} else {
|
||||
this.send(str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hint at view path resolution, outputting the
|
||||
* paths that Express has tried.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function hintAtViewPaths(view, options) {
|
||||
console.error();
|
||||
console.error('failed to locate view "' + view.view + '", tried:');
|
||||
options.attempts.forEach(function(path){
|
||||
console.error(' - %s', path);
|
||||
});
|
||||
console.error();
|
||||
}
|
||||
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);
|
||||
};
|
||||
|
||||
40
test/node_modules/express/lib/view/partial.js
generated
vendored
40
test/node_modules/express/lib/view/partial.js
generated
vendored
@@ -1,40 +0,0 @@
|
||||
|
||||
/*!
|
||||
* Express - view - Partial
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Memory cache.
|
||||
*/
|
||||
|
||||
var cache = {};
|
||||
|
||||
/**
|
||||
* Resolve partial object name from the view path.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* "user.ejs" becomes "user"
|
||||
* "forum thread.ejs" becomes "forumThread"
|
||||
* "forum/thread/post.ejs" becomes "post"
|
||||
* "blog-post.ejs" becomes "blogPost"
|
||||
*
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.resolveObjectName = function(view){
|
||||
return cache[view] || (cache[view] = view
|
||||
.split('/')
|
||||
.slice(-1)[0]
|
||||
.split('.')[0]
|
||||
.replace(/^_/, '')
|
||||
.replace(/[^a-zA-Z0-9 ]+/g, ' ')
|
||||
.split(/ +/).map(function(word, i){
|
||||
return i
|
||||
? word[0].toUpperCase() + word.substr(1)
|
||||
: word;
|
||||
}).join(''));
|
||||
};
|
||||
210
test/node_modules/express/lib/view/view.js
generated
vendored
210
test/node_modules/express/lib/view/view.js
generated
vendored
@@ -1,210 +0,0 @@
|
||||
|
||||
/*!
|
||||
* Express - View
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var path = require('path')
|
||||
, utils = require('../utils')
|
||||
, extname = path.extname
|
||||
, dirname = path.dirname
|
||||
, basename = path.basename
|
||||
, fs = require('fs')
|
||||
, stat = fs.statSync;
|
||||
|
||||
/**
|
||||
* Expose `View`.
|
||||
*/
|
||||
|
||||
exports = module.exports = View;
|
||||
|
||||
/**
|
||||
* Require cache.
|
||||
*/
|
||||
|
||||
var cache = {};
|
||||
|
||||
/**
|
||||
* Initialize a new `View` with the given `view` path and `options`.
|
||||
*
|
||||
* @param {String} view
|
||||
* @param {Object} options
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function View(view, options) {
|
||||
options = options || {};
|
||||
this.view = view;
|
||||
this.root = options.root;
|
||||
this.relative = false !== options.relative;
|
||||
this.defaultEngine = options.defaultEngine;
|
||||
this.parent = options.parentView;
|
||||
this.basename = basename(view);
|
||||
this.engine = this.resolveEngine();
|
||||
this.extension = '.' + this.engine;
|
||||
this.name = this.basename.replace(this.extension, '');
|
||||
this.path = this.resolvePath();
|
||||
this.dirname = dirname(this.path);
|
||||
if (options.attempts) {
|
||||
if (!~options.attempts.indexOf(this.path))
|
||||
options.attempts.push(this.path);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the view path exists.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('exists', function(){
|
||||
try {
|
||||
stat(this.path);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Resolve view engine.
|
||||
*
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
View.prototype.resolveEngine = function(){
|
||||
// Explicit
|
||||
if (~this.basename.indexOf('.')) return extname(this.basename).substr(1);
|
||||
// Inherit from parent
|
||||
if (this.parent) return this.parent.engine;
|
||||
// Default
|
||||
return this.defaultEngine;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve view path.
|
||||
*
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
View.prototype.resolvePath = function(){
|
||||
var path = this.view;
|
||||
// Implicit engine
|
||||
if (!~this.basename.indexOf('.')) path += this.extension;
|
||||
// Absolute
|
||||
if (utils.isAbsolute(path)) return path;
|
||||
// Relative to parent
|
||||
if (this.relative && this.parent) return this.parent.dirname + '/' + path;
|
||||
// Relative to root
|
||||
return this.root
|
||||
? this.root + '/' + path
|
||||
: path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get view contents. This is a one-time hit, so we
|
||||
* can afford to be sync.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('contents', function(){
|
||||
return fs.readFileSync(this.path, 'utf8');
|
||||
});
|
||||
|
||||
/**
|
||||
* Get template engine api, cache exports to reduce
|
||||
* require() calls.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('templateEngine', function(){
|
||||
var ext = this.extension;
|
||||
return cache[ext] || (cache[ext] = require(this.engine));
|
||||
});
|
||||
|
||||
/**
|
||||
* Return root path alternative.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('rootPath', function(){
|
||||
this.relative = false;
|
||||
return this.resolvePath();
|
||||
});
|
||||
|
||||
/**
|
||||
* Return index path alternative.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('indexPath', function(){
|
||||
return this.dirname
|
||||
+ '/' + this.basename.replace(this.extension, '')
|
||||
+ '/index' + this.extension;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return ../<name>/index path alternative.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('upIndexPath', function(){
|
||||
return this.dirname + '/../' + this.name + '/index' + this.extension;
|
||||
});
|
||||
|
||||
/**
|
||||
* Return _ prefix path alternative
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
View.prototype.__defineGetter__('prefixPath', function(){
|
||||
return this.dirname + '/_' + this.basename;
|
||||
});
|
||||
|
||||
/**
|
||||
* Register the given template engine `exports`
|
||||
* as `ext`. For example we may wish to map ".html"
|
||||
* files to jade:
|
||||
*
|
||||
* app.register('.html', require('jade'));
|
||||
*
|
||||
* or
|
||||
*
|
||||
* app.register('html', require('jade'));
|
||||
*
|
||||
* This is also useful for libraries that may not
|
||||
* match extensions correctly. For example my haml.js
|
||||
* library is installed from npm as "hamljs" so instead
|
||||
* of layout.hamljs, we can register the engine as ".haml":
|
||||
*
|
||||
* app.register('.haml', require('haml-js'));
|
||||
*
|
||||
* @param {String} ext
|
||||
* @param {Object} obj
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.register = function(ext, exports) {
|
||||
if ('.' != ext[0]) ext = '.' + ext;
|
||||
cache[ext] = exports;
|
||||
};
|
||||
Reference in New Issue
Block a user