diff options
author | Timoney, Daniel (dt5972) <dtimoney@att.com> | 2017-02-15 10:37:53 -0500 |
---|---|---|
committer | Timoney, Daniel (dt5972) <dtimoney@att.com> | 2017-02-15 10:40:37 -0500 |
commit | 324ee36fe31763e507b422ab0a88e4230045e205 (patch) | |
tree | d0b04520f6657601c918ce63fd27575977624187 /dgbuilder/dgeflows/node_modules/express/lib | |
parent | f0c97e8db427481e28c0a16b789bc73801b35e47 (diff) |
Initial commit for OpenECOMP SDN-C OA&M
Change-Id: I7ab579fd0d206bf356f36d52dcdf4f71f1fa2680
Signed-off-by: Timoney, Daniel (dt5972) <dtimoney@att.com>
Former-commit-id: 2a9f0edd09581f907e62ec4689b5ac94dd5382ba
Diffstat (limited to 'dgbuilder/dgeflows/node_modules/express/lib')
11 files changed, 3615 insertions, 0 deletions
diff --git a/dgbuilder/dgeflows/node_modules/express/lib/application.js b/dgbuilder/dgeflows/node_modules/express/lib/application.js new file mode 100644 index 00000000..dc18fe37 --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/application.js @@ -0,0 +1,571 @@ +/** + * Module dependencies. + */ + +var finalhandler = require('finalhandler'); +var flatten = require('./utils').flatten; +var Router = require('./router'); +var methods = require('methods'); +var middleware = require('./middleware/init'); +var query = require('./middleware/query'); +var debug = require('debug')('express:application'); +var View = require('./view'); +var http = require('http'); +var compileETag = require('./utils').compileETag; +var compileQueryParser = require('./utils').compileQueryParser; +var compileTrust = require('./utils').compileTrust; +var deprecate = require('depd')('express'); +var merge = require('utils-merge'); +var resolve = require('path').resolve; +var slice = Array.prototype.slice; + +/** + * Application prototype. + */ + +var app = exports = module.exports = {}; + +/** + * Initialize the server. + * + * - setup default configuration + * - setup default middleware + * - setup route reflection methods + * + * @api private + */ + +app.init = function(){ + this.cache = {}; + this.settings = {}; + this.engines = {}; + this.defaultConfiguration(); +}; + +/** + * Initialize application configuration. + * + * @api private + */ + +app.defaultConfiguration = function(){ + // default settings + this.enable('x-powered-by'); + this.set('etag', 'weak'); + var env = process.env.NODE_ENV || 'development'; + this.set('env', env); + this.set('query parser', 'extended'); + this.set('subdomain offset', 2); + this.set('trust proxy', false); + + debug('booting in %s mode', env); + + // inherit protos + this.on('mount', function(parent){ + this.request.__proto__ = parent.request; + this.response.__proto__ = parent.response; + this.engines.__proto__ = parent.engines; + this.settings.__proto__ = parent.settings; + }); + + // setup locals + this.locals = Object.create(null); + + // top-most app is mounted at / + this.mountpath = '/'; + + // default locals + this.locals.settings = this.settings; + + // default configuration + this.set('view', View); + this.set('views', resolve('views')); + this.set('jsonp callback name', 'callback'); + + if (env === 'production') { + this.enable('view cache'); + } + + Object.defineProperty(this, 'router', { + get: function() { + throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.'); + } + }); +}; + +/** + * lazily adds the base router if it has not yet been added. + * + * We cannot add the base router in the defaultConfiguration because + * it reads app settings which might be set after that has run. + * + * @api private + */ +app.lazyrouter = function() { + if (!this._router) { + this._router = new Router({ + caseSensitive: this.enabled('case sensitive routing'), + strict: this.enabled('strict routing') + }); + + this._router.use(query(this.get('query parser fn'))); + this._router.use(middleware.init(this)); + } +}; + +/** + * Dispatch a req, res pair into the application. Starts pipeline processing. + * + * If no _done_ callback is provided, then default error handlers will respond + * in the event of an error bubbling through the stack. + * + * @api private + */ + +app.handle = function(req, res, done) { + var router = this._router; + + // final handler + done = done || finalhandler(req, res, { + env: this.get('env'), + onerror: logerror.bind(this) + }); + + // no routes + if (!router) { + debug('no routes defined on app'); + done(); + return; + } + + router.handle(req, res, done); +}; + +/** + * Proxy `Router#use()` to add middleware to the app router. + * See Router#use() documentation for details. + * + * If the _fn_ parameter is an express app, then it will be + * mounted at the _route_ specified. + * + * @api public + */ + +app.use = function use(fn) { + var offset = 0; + var path = '/'; + + // default path to '/' + // disambiguate app.use([fn]) + if (typeof fn !== 'function') { + var arg = fn; + + while (Array.isArray(arg) && arg.length !== 0) { + arg = arg[0]; + } + + // first arg is the path + if (typeof arg !== 'function') { + offset = 1; + path = fn; + } + } + + var fns = flatten(slice.call(arguments, offset)); + + if (fns.length === 0) { + throw new TypeError('app.use() requires middleware functions'); + } + + // setup router + this.lazyrouter(); + var router = this._router; + + fns.forEach(function (fn) { + // non-express app + if (!fn || !fn.handle || !fn.set) { + return router.use(path, fn); + } + + debug('.use app under %s', path); + fn.mountpath = path; + fn.parent = this; + + // restore .app property on req and res + router.use(path, function mounted_app(req, res, next) { + var orig = req.app; + fn.handle(req, res, function (err) { + req.__proto__ = orig.request; + res.__proto__ = orig.response; + next(err); + }); + }); + + // mounted an app + fn.emit('mount', this); + }, this); + + return this; +}; + +/** + * Proxy to the app `Router#route()` + * Returns a new `Route` instance for the _path_. + * + * Routes are isolated middleware stacks for specific paths. + * See the Route api docs for details. + * + * @api public + */ + +app.route = function(path){ + this.lazyrouter(); + return this._router.route(path); +}; + +/** + * 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/tj/consolidate.js) + * library was created to map all of node's popular template + * engines to follow this convention, thus allowing them to + * work seamlessly within Express. + * + * @param {String} ext + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.engine = function(ext, fn){ + if ('function' != typeof fn) throw new Error('callback function required'); + if ('.' != ext[0]) ext = '.' + ext; + this.engines[ext] = fn; + return this; +}; + +/** + * Proxy to `Router#param()` with one added api feature. The _name_ parameter + * can be an array of names. + * + * See the Router#param() docs for more details. + * + * @param {String|Array} name + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +app.param = function(name, fn){ + this.lazyrouter(); + + if (Array.isArray(name)) { + name.forEach(function(key) { + this.param(key, fn); + }, this); + return this; + } + + this._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 {*} [val] + * @return {Server} for chaining + * @api public + */ + +app.set = function(setting, val){ + if (arguments.length === 1) { + // app.get(setting) + return this.settings[setting]; + } + + // set value + this.settings[setting] = val; + + // trigger matched settings + switch (setting) { + case 'etag': + debug('compile etag %s', val); + this.set('etag fn', compileETag(val)); + break; + case 'query parser': + debug('compile query parser %s', val); + this.set('query parser fn', compileQueryParser(val)); + break; + case 'trust proxy': + debug('compile trust proxy %s', val); + this.set('trust proxy fn', compileTrust(val)); + break; + } + + 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.mountpath + : ''; +}; + +/** + * 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); +}; + +/** + * Delegate `.VERB(...)` calls to `router.VERB(...)`. + */ + +methods.forEach(function(method){ + app[method] = function(path){ + if ('get' == method && 1 == arguments.length) return this.set(path); + + this.lazyrouter(); + + var route = this._router.route(path); + route[method].apply(route, slice.call(arguments, 1)); + 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){ + this.lazyrouter(); + + var route = this._router.route(path); + var args = slice.call(arguments, 1); + methods.forEach(function(method){ + route[method].apply(route, args); + }); + + return this; +}; + +// del -> delete alias + +app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead'); + +/** + * 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 = {}; + var cache = this.cache; + var engines = this.engines; + var view; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge app.locals + merge(opts, this.locals); + + // merge options._locals + if (options._locals) { + merge(opts, options._locals); + } + + // merge options + merge(opts, options); + + // set .cache unless explicitly provided + opts.cache = null == opts.cache + ? this.enabled('view cache') + : opts.cache; + + // primed cache + if (opts.cache) view = cache[name]; + + // view + if (!view) { + view = new (this.get('view'))(name, { + defaultEngine: this.get('view engine'), + root: this.get('views'), + engines: engines + }); + + if (!view.path) { + var dirs = Array.isArray(view.root) && view.root.length > 1 + ? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"' + : 'directory "' + view.root + '"' + var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs); + 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); +}; + +/** +* Log error using console.error. +* +* @param {Error} err +* @api private +*/ + +function logerror(err){ + if (this.get('env') !== 'test') console.error(err.stack || err.toString()); +} diff --git a/dgbuilder/dgeflows/node_modules/express/lib/express.js b/dgbuilder/dgeflows/node_modules/express/lib/express.js new file mode 100644 index 00000000..8a6c2846 --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/express.js @@ -0,0 +1,93 @@ +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; +var mixin = require('merge-descriptors'); +var proto = require('./application'); +var Route = require('./router/route'); +var Router = require('./router'); +var req = require('./request'); +var res = require('./response'); + +/** + * Expose `createApplication()`. + */ + +exports = module.exports = createApplication; + +/** + * Create an express application. + * + * @return {Function} + * @api public + */ + +function createApplication() { + var app = function(req, res, next) { + app.handle(req, res, next); + }; + + mixin(app, proto); + mixin(app, EventEmitter.prototype); + + app.request = { __proto__: req, app: app }; + app.response = { __proto__: res, app: app }; + app.init(); + return app; +} + +/** + * Expose the prototypes. + */ + +exports.application = proto; +exports.request = req; +exports.response = res; + +/** + * Expose constructors. + */ + +exports.Route = Route; +exports.Router = Router; + +/** + * Expose middleware + */ + +exports.query = require('./middleware/query'); +exports.static = require('serve-static'); + +/** + * Replace removed middleware with an appropriate error message. + */ + +[ + 'json', + 'urlencoded', + 'bodyParser', + 'compress', + 'cookieSession', + 'session', + 'logger', + 'cookieParser', + 'favicon', + 'responseTime', + 'errorHandler', + 'timeout', + 'methodOverride', + 'vhost', + 'csrf', + 'directory', + 'limit', + 'multipart', + 'staticCache', +].forEach(function (name) { + Object.defineProperty(exports, name, { + get: function () { + throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.'); + }, + configurable: true + }); +}); diff --git a/dgbuilder/dgeflows/node_modules/express/lib/middleware/init.js b/dgbuilder/dgeflows/node_modules/express/lib/middleware/init.js new file mode 100644 index 00000000..1e3e903f --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/middleware/init.js @@ -0,0 +1,26 @@ +/** + * Initialization middleware, exposing the + * request and response to each other, 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){ + if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express'); + req.res = res; + res.req = req; + req.next = next; + + req.__proto__ = app.request; + res.__proto__ = app.response; + + res.locals = res.locals || Object.create(null); + + next(); + }; +}; + diff --git a/dgbuilder/dgeflows/node_modules/express/lib/middleware/query.js b/dgbuilder/dgeflows/node_modules/express/lib/middleware/query.js new file mode 100644 index 00000000..092bbd99 --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/middleware/query.js @@ -0,0 +1,30 @@ +/** + * Module dependencies. + */ + +var parseUrl = require('parseurl'); +var qs = require('qs'); + +/** + * @param {Object} options + * @return {Function} + * @api public + */ + +module.exports = function query(options) { + var queryparse = qs.parse; + + if (typeof options === 'function') { + queryparse = options; + options = undefined; + } + + return function query(req, res, next){ + if (!req.query) { + var val = parseUrl(req).query; + req.query = queryparse(val, options); + } + + next(); + }; +}; diff --git a/dgbuilder/dgeflows/node_modules/express/lib/request.js b/dgbuilder/dgeflows/node_modules/express/lib/request.js new file mode 100644 index 00000000..5cd3900e --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/request.js @@ -0,0 +1,467 @@ +/** + * Module dependencies. + */ + +var accepts = require('accepts'); +var deprecate = require('depd')('express'); +var isIP = require('net').isIP; +var typeis = require('type-is'); +var http = require('http'); +var fresh = require('fresh'); +var parseRange = require('range-parser'); +var parse = require('parseurl'); +var proxyaddr = require('proxy-addr'); + +/** + * Request prototype. + */ + +var req = exports = module.exports = { + __proto__: http.IncomingMessage.prototype +}; + +/** + * Return request header. + * + * The `Referrer` header field is special-cased, + * both `Referrer` and `Referer` are interchangeable. + * + * Examples: + * + * req.get('Content-Type'); + * // => "text/plain" + * + * req.get('content-type'); + * // => "text/plain" + * + * req.get('Something'); + * // => undefined + * + * Aliased as `req.header()`. + * + * @param {String} name + * @return {String} + * @api public + */ + +req.get = +req.header = function(name){ + switch (name = name.toLowerCase()) { + case 'referer': + case 'referrer': + return this.headers.referrer + || this.headers.referer; + default: + return this.headers[name]; + } +}; + +/** + * To do: update docs. + * + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json", a comma-delimted list such as "json, html, text/plain", + * an argument list such as `"json", "html", "text/plain"`, + * or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * req.accepts('html'); + * // => "html" + * + * // Accept: text/*, application/json + * req.accepts('html'); + * // => "html" + * req.accepts('text/html'); + * // => "text/html" + * req.accepts('json, text'); + * // => "json" + * req.accepts('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * req.accepts('image/png'); + * req.accepts('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * req.accepts(['html', 'json']); + * req.accepts('html', 'json'); + * req.accepts('html, json'); + * // => "json" + * + * @param {String|Array} type(s) + * @return {String} + * @api public + */ + +req.accepts = function(){ + var accept = accepts(this); + return accept.types.apply(accept, arguments); +}; + +/** + * Check if the given `encoding`s are accepted. + * + * @param {String} ...encoding + * @return {Boolean} + * @api public + */ + +req.acceptsEncodings = function(){ + var accept = accepts(this); + return accept.encodings.apply(accept, arguments); +}; + +req.acceptsEncoding = deprecate.function(req.acceptsEncodings, + 'req.acceptsEncoding: Use acceptsEncodings instead'); + +/** + * Check if the given `charset`s are acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} ...charset + * @return {Boolean} + * @api public + */ + +req.acceptsCharsets = function(){ + var accept = accepts(this); + return accept.charsets.apply(accept, arguments); +}; + +req.acceptsCharset = deprecate.function(req.acceptsCharsets, + 'req.acceptsCharset: Use acceptsCharsets instead'); + +/** + * Check if the given `lang`s are acceptable, + * otherwise you should respond with 406 "Not Acceptable". + * + * @param {String} ...lang + * @return {Boolean} + * @api public + */ + +req.acceptsLanguages = function(){ + var accept = accepts(this); + return accept.languages.apply(accept, arguments); +}; + +req.acceptsLanguage = deprecate.function(req.acceptsLanguages, + 'req.acceptsLanguage: Use acceptsLanguages instead'); + +/** + * 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 the value of param `name` when present or `defaultValue`. + * + * - Checks route placeholders, ex: _/user/:id_ + * - Checks body params, ex: id=12, {"id":12} + * - Checks query string params, ex: ?id=12 + * + * To utilize request bodies, `req.body` + * should be an object. This can be done by using + * the `bodyParser()` middleware. + * + * @param {String} name + * @param {Mixed} [defaultValue] + * @return {String} + * @api public + */ + +req.param = function param(name, defaultValue) { + var params = this.params || {}; + var body = this.body || {}; + var query = this.query || {}; + + var args = arguments.length === 1 + ? 'name' + : 'name, default'; + deprecate('req.param(' + args + '): Use req.params, req.body, or req.query instead'); + + if (null != params[name] && params.hasOwnProperty(name)) return params[name]; + if (null != body[name]) return body[name]; + if (null != query[name]) return query[name]; + + return defaultValue; +}; + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains the give mime `type`. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * req.is('html'); + * req.is('text/html'); + * req.is('text/*'); + * // => true + * + * // When Content-Type is application/json + * req.is('json'); + * req.is('application/json'); + * req.is('application/*'); + * // => true + * + * req.is('html'); + * // => false + * + * @param {String} type + * @return {Boolean} + * @api public + */ + +req.is = function(types){ + if (!Array.isArray(types)) types = [].slice.call(arguments); + return typeis(this, types); +}; + +/** + * Return the protocol string "http" or "https" + * when requested with TLS. When the "trust proxy" + * setting trusts the socket address, the + * "X-Forwarded-Proto" header field will be trusted + * and used if present. + * + * If you're running behind a reverse proxy that + * supplies https for you this may be enabled. + * + * @return {String} + * @api public + */ + +defineGetter(req, 'protocol', function protocol(){ + var proto = this.connection.encrypted + ? 'https' + : 'http'; + var trust = this.app.get('trust proxy fn'); + + if (!trust(this.connection.remoteAddress)) { + return proto; + } + + // Note: X-Forwarded-Proto is normally only ever a + // single value, but this is to be safe. + proto = this.get('X-Forwarded-Proto') || proto; + return proto.split(/\s*,\s*/)[0]; +}); + +/** + * Short-hand for: + * + * req.protocol == 'https' + * + * @return {Boolean} + * @api public + */ + +defineGetter(req, 'secure', function secure(){ + return 'https' == this.protocol; +}); + +/** + * Return the remote address from the trusted proxy. + * + * The is the remote address on the socket unless + * "trust proxy" is set. + * + * @return {String} + * @api public + */ + +defineGetter(req, 'ip', function ip(){ + var trust = this.app.get('trust proxy fn'); + return proxyaddr(this, trust); +}); + +/** + * When "trust proxy" is set, trusted proxy addresses + client. + * + * For example if the value were "client, proxy1, proxy2" + * you would receive the array `["client", "proxy1", "proxy2"]` + * where "proxy2" is the furthest down-stream and "proxy1" and + * "proxy2" were trusted. + * + * @return {Array} + * @api public + */ + +defineGetter(req, 'ips', function ips() { + var trust = this.app.get('trust proxy fn'); + var addrs = proxyaddr.all(this, trust); + return addrs.slice(1).reverse(); +}); + +/** + * Return subdomains as an array. + * + * Subdomains are the dot-separated parts of the host before the main domain of + * the app. By default, the domain of the app is assumed to be the last two + * parts of the host. This can be changed by setting "subdomain offset". + * + * For example, if the domain is "tobi.ferrets.example.com": + * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. + * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. + * + * @return {Array} + * @api public + */ + +defineGetter(req, 'subdomains', function subdomains() { + var hostname = this.hostname; + + if (!hostname) return []; + + var offset = this.app.get('subdomain offset'); + var subdomains = !isIP(hostname) + ? hostname.split('.').reverse() + : [hostname]; + + return subdomains.slice(offset); +}); + +/** + * Short-hand for `url.parse(req.url).pathname`. + * + * @return {String} + * @api public + */ + +defineGetter(req, 'path', function path() { + return parse(this).pathname; +}); + +/** + * Parse the "Host" header field to a hostname. + * + * When the "trust proxy" setting trusts the socket + * address, the "X-Forwarded-Host" header field will + * be trusted. + * + * @return {String} + * @api public + */ + +defineGetter(req, 'hostname', function hostname(){ + var trust = this.app.get('trust proxy fn'); + var host = this.get('X-Forwarded-Host'); + + if (!host || !trust(this.connection.remoteAddress)) { + host = this.get('Host'); + } + + if (!host) return; + + // IPv6 literal support + var offset = host[0] === '[' + ? host.indexOf(']') + 1 + : 0; + var index = host.indexOf(':', offset); + + return ~index + ? host.substring(0, index) + : host; +}); + +// TODO: change req.host to return host in next major + +defineGetter(req, 'host', deprecate.function(function host(){ + return this.hostname; +}, 'req.host: Use req.hostname instead')); + +/** + * Check if the request is fresh, aka + * Last-Modified and/or the ETag + * still match. + * + * @return {Boolean} + * @api public + */ + +defineGetter(req, '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 + */ + +defineGetter(req, 'stale', function stale(){ + return !this.fresh; +}); + +/** + * Check if the request was an _XMLHttpRequest_. + * + * @return {Boolean} + * @api public + */ + +defineGetter(req, 'xhr', function xhr(){ + var val = this.get('X-Requested-With') || ''; + return 'xmlhttprequest' == val.toLowerCase(); +}); + +/** + * Helper function for creating a getter on an object. + * + * @param {Object} obj + * @param {String} name + * @param {Function} getter + * @api private + */ +function defineGetter(obj, name, getter) { + Object.defineProperty(obj, name, { + configurable: true, + enumerable: true, + get: getter + }); +}; diff --git a/dgbuilder/dgeflows/node_modules/express/lib/response.js b/dgbuilder/dgeflows/node_modules/express/lib/response.js new file mode 100644 index 00000000..14aa9cab --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/response.js @@ -0,0 +1,1024 @@ +/** + * Module dependencies. + */ + +var contentDisposition = require('content-disposition'); +var deprecate = require('depd')('express'); +var escapeHtml = require('escape-html'); +var http = require('http'); +var isAbsolute = require('./utils').isAbsolute; +var onFinished = require('on-finished'); +var path = require('path'); +var merge = require('utils-merge'); +var sign = require('cookie-signature').sign; +var normalizeType = require('./utils').normalizeType; +var normalizeTypes = require('./utils').normalizeTypes; +var setCharset = require('./utils').setCharset; +var statusCodes = http.STATUS_CODES; +var cookie = require('cookie'); +var send = require('send'); +var extname = path.extname; +var mime = send.mime; +var resolve = path.resolve; +var vary = require('vary'); + +/** + * Response prototype. + */ + +var res = module.exports = { + __proto__: http.ServerResponse.prototype +}; + +/** + * Set status `code`. + * + * @param {Number} code + * @return {ServerResponse} + * @api public + */ + +res.status = function(code){ + this.statusCode = code; + return this; +}; + +/** + * Set Link header field with the given `links`. + * + * Examples: + * + * res.links({ + * next: 'http://api.example.com/users?page=2', + * last: 'http://api.example.com/users?page=5' + * }); + * + * @param {Object} links + * @return {ServerResponse} + * @api public + */ + +res.links = function(links){ + var link = this.get('Link') || ''; + if (link) link += ', '; + return this.set('Link', 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>'); + * + * @param {string|number|boolean|object|Buffer} body + * @api public + */ + +res.send = function send(body) { + var chunk = body; + var encoding; + var len; + var req = this.req; + var type; + + // settings + var app = this.app; + + // allow status / body + if (arguments.length === 2) { + // res.send(body, status) backwards compat + if (typeof arguments[0] !== 'number' && typeof arguments[1] === 'number') { + deprecate('res.send(body, status): Use res.status(status).send(body) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.send(status, body): Use res.status(status).send(body) instead'); + this.statusCode = arguments[0]; + chunk = arguments[1]; + } + } + + // disambiguate res.send(status) and res.send(status, num) + if (typeof chunk === 'number' && arguments.length === 1) { + // res.send(status) will set status message as text string + if (!this.get('Content-Type')) { + this.type('txt'); + } + + deprecate('res.send(status): Use res.sendStatus(status) instead'); + this.statusCode = chunk; + chunk = http.STATUS_CODES[chunk]; + } + + switch (typeof chunk) { + // string defaulting to html + case 'string': + if (!this.get('Content-Type')) { + this.type('html'); + } + break; + case 'boolean': + case 'number': + case 'object': + if (chunk === null) { + chunk = ''; + } else if (Buffer.isBuffer(chunk)) { + if (!this.get('Content-Type')) { + this.type('bin'); + } + } else { + return this.json(chunk); + } + break; + } + + // write strings in utf-8 + if (typeof chunk === 'string') { + encoding = 'utf8'; + type = this.get('Content-Type'); + + // reflect this in content-type + if (typeof type === 'string') { + this.set('Content-Type', setCharset(type, 'utf-8')); + } + } + + // populate Content-Length + if (chunk !== undefined) { + if (!Buffer.isBuffer(chunk)) { + // convert chunk to Buffer; saves later double conversions + chunk = new Buffer(chunk, encoding); + encoding = undefined; + } + + len = chunk.length; + this.set('Content-Length', len); + } + + // method check + var isHead = req.method === 'HEAD'; + + // ETag support + if (len !== undefined && (isHead || req.method === 'GET')) { + var etag = app.get('etag fn'); + if (etag && !this.get('ETag')) { + etag = etag(chunk, encoding); + etag && this.set('ETag', etag); + } + } + + // 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'); + chunk = ''; + } + + if (isHead) { + // skip body for HEAD + this.end(); + } else { + // respond + this.end(chunk, encoding); + } + + return this; +}; + +/** + * Send JSON response. + * + * Examples: + * + * res.json(null); + * res.json({ user: 'tj' }); + * + * @param {string|number|boolean|object} obj + * @api public + */ + +res.json = function json(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.json(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.json(status, obj): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(val, replacer, spaces); + + // content-type + if (!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' }); + * + * @param {string|number|boolean|object} obj + * @api public + */ + +res.jsonp = function jsonp(obj) { + var val = obj; + + // allow status / body + if (arguments.length === 2) { + // res.json(body, status) backwards compat + if (typeof arguments[1] === 'number') { + deprecate('res.jsonp(obj, status): Use res.status(status).json(obj) instead'); + this.statusCode = arguments[1]; + } else { + deprecate('res.jsonp(status, obj): Use res.status(status).jsonp(obj) instead'); + this.statusCode = arguments[0]; + val = arguments[1]; + } + } + + // settings + var app = this.app; + var replacer = app.get('json replacer'); + var spaces = app.get('json spaces'); + var body = JSON.stringify(val, replacer, spaces); + var callback = this.req.query[app.get('jsonp callback name')]; + + // content-type + if (!this.get('Content-Type')) { + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'application/json'); + } + + // fixup callback + if (Array.isArray(callback)) { + callback = callback[0]; + } + + // jsonp + if (typeof callback === 'string' && callback.length !== 0) { + this.charset = 'utf-8'; + this.set('X-Content-Type-Options', 'nosniff'); + this.set('Content-Type', 'text/javascript'); + + // restrict callback charset + callback = callback.replace(/[^\[\]\w$.]/g, ''); + + // replace chars not allowed in JavaScript that are in JSON + body = body + .replace(/\u2028/g, '\\u2028') + .replace(/\u2029/g, '\\u2029'); + + // the /**/ is a specific security mitigation for "Rosetta Flash JSONP abuse" + // the typeof check is just to reduce client error noise + body = '/**/ typeof ' + callback + ' === \'function\' && ' + callback + '(' + body + ');'; + } + + return this.send(body); +}; + +/** + * Send given HTTP status code. + * + * Sets the response status to `statusCode` and the body of the + * response to the standard description from node's http.STATUS_CODES + * or the statusCode number if no description. + * + * Examples: + * + * res.sendStatus(200); + * + * @param {number} statusCode + * @api public + */ + +res.sendStatus = function sendStatus(statusCode) { + var body = http.STATUS_CODES[statusCode] || String(statusCode); + + this.statusCode = statusCode; + this.type('txt'); + + 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 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * 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.'); + * } + * }); + * }); + * + * @api public + */ + +res.sendFile = function sendFile(path, options, fn) { + var req = this.req; + var res = this; + var next = req.next; + + if (!path) { + throw new TypeError('path argument is required to res.sendFile'); + } + + // support function as second arg + if (typeof options === 'function') { + fn = options; + options = {}; + } + + options = options || {}; + + if (!options.root && !isAbsolute(path)) { + throw new TypeError('path must be absolute or specify root to res.sendFile'); + } + + // create file stream + var pathname = encodeURI(path); + var file = send(req, pathname, options); + + // transfer + sendfile(res, file, options, function (err) { + if (fn) return fn(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORT' && err.syscall !== 'write') { + next(err); + } + }); +}; + +/** + * 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 (can be string converted by `ms`) + * - `root` root directory for relative filenames + * - `headers` object of headers to serve with file + * - `dotfiles` serve dotfiles, defaulting to false; can be `"allow"` to send them + * + * Other options are passed along to `send`. + * + * 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.'); + * } + * }); + * }); + * + * @api public + */ + +res.sendfile = function(path, options, fn){ + var req = this.req; + var res = this; + var next = req.next; + + // support function as second arg + if (typeof options === 'function') { + fn = options; + options = {}; + } + + options = options || {}; + + // create file stream + var file = send(req, path, options); + + // transfer + sendfile(res, file, options, function (err) { + if (fn) return fn(err); + if (err && err.code === 'EISDIR') return next(); + + // next() all but write errors + if (err && err.code !== 'ECONNABORT' && err.syscall !== 'write') { + next(err); + } + }); +}; + +res.sendfile = deprecate.function(res.sendfile, + 'res.sendfile: Use res.sendFile instead'); + +/** + * Transfer the file at the given `path` as an attachment. + * + * Optionally providing an alternate attachment `filename`, + * and optional callback `fn(err)`. The callback is invoked + * when the data transfer is complete, or when an error has + * ocurred. Be sure to check `res.headersSent` if you plan to respond. + * + * This method uses `res.sendfile()`. + * + * @api public + */ + +res.download = function download(path, filename, fn) { + // support function as second arg + if (typeof filename === 'function') { + fn = filename; + filename = null; + } + + filename = filename || path; + + // set Content-Disposition when file is sent + var headers = { + 'Content-Disposition': contentDisposition(filename) + }; + + // Resolve the full path for sendFile + var fullPath = resolve(path); + + return this.sendFile(fullPath, { headers: headers }, 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; + var next = req.next; + + var fn = obj.default; + if (fn) delete obj.default; + var keys = Object.keys(obj); + + var key = req.accepts(keys); + + this.vary("Accept"); + + if (key) { + this.set('Content-Type', normalizeType(key).value); + obj[key](req, this, next); + } else if (fn) { + fn(); + } else { + var err = new Error('Not Acceptable'); + err.status = 406; + err.types = normalizeTypes(keys).map(function(o){ return o.value }); + next(err); + } + + return this; +}; + +/** + * Set _Content-Disposition_ header to _attachment_ with optional `filename`. + * + * @param {String} filename + * @return {ServerResponse} + * @api public + */ + +res.attachment = function attachment(filename) { + if (filename) { + this.type(extname(filename)); + } + + this.set('Content-Disposition', contentDisposition(filename)); + + return this; +}; + +/** + * Append additional header `field` with value `val`. + * + * Example: + * + * res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']); + * res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly'); + * res.append('Warning', '199 Miscellaneous warning'); + * + * @param {String} field + * @param {String|Array} val + * @return {ServerResponse} for chaining + * @api public + */ + +res.append = function append(field, val) { + var prev = this.get(field); + var value = val; + + if (prev) { + // concat the new and prev vals + value = Array.isArray(prev) ? prev.concat(val) + : Array.isArray(val) ? [prev].concat(val) + : [prev, val]; + } + + return this.set(field, value); +}; + +/** + * Set header `field` to `val`, or pass + * an object of header fields. + * + * Examples: + * + * res.set('Foo', ['bar', 'baz']); + * res.set('Accept', 'application/json'); + * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); + * + * Aliased as `res.header()`. + * + * @param {String|Object|Array} field + * @param {String} val + * @return {ServerResponse} for chaining + * @api public + */ + +res.set = +res.header = function header(field, val) { + if (arguments.length === 2) { + if (Array.isArray(val)) val = val.map(String); + else val = String(val); + if ('content-type' == field.toLowerCase() && !/;\s*charset\s*=/.test(val)) { + var charset = mime.charsets.lookup(val.split(';')[0]); + if (charset) val += '; charset=' + charset.toLowerCase(); + } + this.setHeader(field, val); + } else { + for (var key in field) { + this.set(key, field[key]); + } + } + return this; +}; + +/** + * Get value for header `field`. + * + * @param {String} field + * @return {String} + * @api public + */ + +res.get = function(field){ + return this.getHeader(field); +}; + +/** + * Clear cookie `name`. + * + * @param {String} name + * @param {Object} options + * @return {ServerResponse} for chaining + * @api public + */ + +res.clearCookie = function(name, options){ + var opts = { expires: new Date(1), path: '/' }; + return this.cookie(name, '', options + ? merge(opts, options) + : opts); +}; + +/** + * Set cookie `name` to `val`, with the given `options`. + * + * Options: + * + * - `maxAge` max-age in milliseconds, converted to `expires` + * - `signed` sign the cookie + * - `path` defaults to "/" + * + * Examples: + * + * // "Remember Me" for 15 minutes + * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + * + * // save as above + * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + * + * @param {String} name + * @param {String|Object} val + * @param {Options} options + * @return {ServerResponse} for chaining + * @api public + */ + +res.cookie = function(name, val, options){ + options = merge({}, options); + var secret = this.req.secret; + var signed = options.signed; + if (signed && !secret) throw new Error('cookieParser("secret") required for signed cookies'); + if ('number' == typeof val) val = val.toString(); + 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 = '/'; + var headerVal = cookie.serialize(name, String(val), options); + + // supports multiple 'res.cookie' calls by getting previous value + var prev = this.get('Set-Cookie'); + if (prev) { + if (Array.isArray(prev)) { + headerVal = prev.concat(headerVal); + } else { + headerVal = [prev, headerVal]; + } + } + this.set('Set-Cookie', headerVal); + return this; +}; + + +/** + * Set the location header to `url`. + * + * The given `url` can also be "back", which redirects + * to the _Referrer_ or _Referer_ headers or "/". + * + * Examples: + * + * res.location('/foo/bar').; + * res.location('http://example.com'); + * res.location('../login'); + * + * @param {String} url + * @return {ServerResponse} for chaining + * @api public + */ + +res.location = function(url){ + var req = this.req; + + // "back" is an alias for the referrer + if ('back' == url) url = req.get('Referrer') || '/'; + + // Respond + this.set('Location', url); + return this; +}; + +/** + * Redirect to the given `url` with optional response `status` + * defaulting to 302. + * + * The resulting `url` is determined by `res.location()`, so + * it will play nicely with mounted apps, relative paths, + * `"back"` etc. + * + * Examples: + * + * res.redirect('/foo/bar'); + * res.redirect('http://example.com'); + * res.redirect(301, 'http://example.com'); + * res.redirect('../login'); // /blog/post/1 -> /blog/login + * + * @api public + */ + +res.redirect = function redirect(url) { + var address = url; + var body; + var status = 302; + + // allow status / url + if (arguments.length === 2) { + if (typeof arguments[0] === 'number') { + status = arguments[0]; + address = arguments[1]; + } else { + deprecate('res.redirect(url, status): Use res.redirect(status, url) instead'); + status = arguments[1]; + } + } + + // Set location header + this.location(address); + address = this.get('Location'); + + // Support text/{plain,html} by default + this.format({ + text: function(){ + body = statusCodes[status] + '. Redirecting to ' + encodeURI(address); + }, + + html: function(){ + var u = escapeHtml(address); + body = '<p>' + statusCodes[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>'; + }, + + default: function(){ + body = ''; + } + }); + + // Respond + this.statusCode = status; + this.set('Content-Length', Buffer.byteLength(body)); + + if (this.req.method === 'HEAD') { + this.end(); + } else { + this.end(body); + } +}; + +/** + * Add `field` to Vary. If already present in the Vary set, then + * this call is simply ignored. + * + * @param {Array|String} field + * @return {ServerResponse} for chaining + * @api public + */ + +res.vary = function(field){ + // checks for back-compat + if (!field || (Array.isArray(field) && !field.length)) { + deprecate('res.vary(): Provide a field name'); + return this; + } + + vary(this, field); + + return this; +}; + +/** + * Render `view` with the given `options` and optional callback `fn`. + * When a callback function is given a response will _not_ be made + * automatically, otherwise a response of _200_ and _text/html_ is given. + * + * Options: + * + * - `cache` boolean hinting to the engine it should cache + * - `filename` filename of the view being rendered + * + * @api public + */ + +res.render = function(view, options, fn){ + options = options || {}; + var self = this; + var req = this.req; + var app = req.app; + + // support callback function as second arg + if ('function' == typeof options) { + fn = options, options = {}; + } + + // merge res.locals + options._locals = self.locals; + + // default callback to respond + fn = fn || function(err, str){ + if (err) return req.next(err); + self.send(str); + }; + + // render + app.render(view, options, fn); +}; + +// pipe the send file stream +function sendfile(res, file, options, callback) { + var done = false; + var streaming; + + // request aborted + function onaborted() { + if (done) return; + done = true; + + var err = new Error('Request aborted'); + err.code = 'ECONNABORT'; + callback(err); + } + + // directory + function ondirectory() { + if (done) return; + done = true; + + var err = new Error('EISDIR, read'); + err.code = 'EISDIR'; + callback(err); + } + + // errors + function onerror(err) { + if (done) return; + done = true; + callback(err); + } + + // ended + function onend() { + if (done) return; + done = true; + callback(); + } + + // file + function onfile() { + streaming = false; + } + + // finished + function onfinish(err) { + if (err) return onerror(err); + if (done) return; + + setImmediate(function () { + if (streaming !== false && !done) { + onaborted(); + return; + } + + if (done) return; + done = true; + callback(); + }); + } + + // streaming + function onstream() { + streaming = true; + } + + file.on('directory', ondirectory); + file.on('end', onend); + file.on('error', onerror); + file.on('file', onfile); + file.on('stream', onstream); + onFinished(res, onfinish); + + if (options.headers) { + // set headers on successful transfer + file.on('headers', function headers(res) { + var obj = options.headers; + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + var k = keys[i]; + res.setHeader(k, obj[k]); + } + }); + } + + // pipe + file.pipe(res); +} diff --git a/dgbuilder/dgeflows/node_modules/express/lib/router/index.js b/dgbuilder/dgeflows/node_modules/express/lib/router/index.js new file mode 100644 index 00000000..209f881b --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/router/index.js @@ -0,0 +1,630 @@ + +/** + * Module dependencies. + */ + +var Route = require('./route'); +var Layer = require('./layer'); +var methods = require('methods'); +var mixin = require('utils-merge'); +var debug = require('debug')('express:router'); +var deprecate = require('depd')('express'); +var parseUrl = require('parseurl'); +var utils = require('../utils'); + +/** + * Module variables. + */ + +var objectRegExp = /^\[object (\S+)\]$/; +var slice = Array.prototype.slice; +var toString = Object.prototype.toString; + +/** + * Initialize a new `Router` with the given `options`. + * + * @param {Object} options + * @return {Router} which is an callable function + * @api public + */ + +var proto = module.exports = function(options) { + options = options || {}; + + function router(req, res, next) { + router.handle(req, res, next); + } + + // mixin Router class functions + router.__proto__ = proto; + + router.params = {}; + router._params = []; + router.caseSensitive = options.caseSensitive; + router.mergeParams = options.mergeParams; + router.strict = options.strict; + router.stack = []; + + return router; +}; + +/** + * Map the given param placeholder `name`(s) to the given callback. + * + * 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 same signature as middleware, the only difference + * 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. + * + * Just like in middleware, you must either respond to the request or call next + * to avoid stalling the request. + * + * app.param('user_id', function(req, res, next, id){ + * User.find(id, function(err, user){ + * if (err) { + * return next(err); + * } else if (!user) { + * return next(new Error('failed to load user')); + * } + * req.user = user; + * next(); + * }); + * }); + * + * @param {String} name + * @param {Function} fn + * @return {app} for chaining + * @api public + */ + +proto.param = function param(name, fn) { + // param logic + if (typeof name === 'function') { + deprecate('router.param(fn): Refactor to use path params'); + this._params.push(name); + return; + } + + // apply param functions + var params = this._params; + var len = params.length; + var ret; + + if (name[0] === ':') { + deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead'); + name = name.substr(1); + } + + for (var i = 0; i < len; ++i) { + if (ret = params[i](name, fn)) { + fn = ret; + } + } + + // ensure we end up with a + // middleware function + if ('function' != typeof fn) { + throw new Error('invalid param() call for ' + name + ', got ' + fn); + } + + (this.params[name] = this.params[name] || []).push(fn); + return this; +}; + +/** + * Dispatch a req, res into the router. + * + * @api private + */ + +proto.handle = function(req, res, done) { + var self = this; + + debug('dispatching %s %s', req.method, req.url); + + var search = 1 + req.url.indexOf('?'); + var pathlength = search ? search - 1 : req.url.length; + var fqdn = req.url[0] !== '/' && 1 + req.url.substr(0, pathlength).indexOf('://'); + var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : ''; + var idx = 0; + var removed = ''; + var slashAdded = false; + var paramcalled = {}; + + // store options for OPTIONS request + // only used if OPTIONS request + var options = []; + + // middleware and routes + var stack = self.stack; + + // manage inter-router variables + var parentParams = req.params; + var parentUrl = req.baseUrl || ''; + done = restore(done, req, 'baseUrl', 'next', 'params'); + + // setup next layer + req.next = next; + + // for options requests, respond with a default if nothing else responds + if (req.method === 'OPTIONS') { + done = wrap(done, function(old, err) { + if (err || options.length === 0) return old(err); + sendOptionsResponse(res, options, old); + }); + } + + // setup basic req values + req.baseUrl = parentUrl; + req.originalUrl = req.originalUrl || req.url; + + next(); + + function next(err) { + var layerError = err === 'route' + ? null + : err; + + // remove added slash + if (slashAdded) { + req.url = req.url.substr(1); + slashAdded = false; + } + + // restore altered req.url + if (removed.length !== 0) { + req.baseUrl = parentUrl; + req.url = protohost + removed + req.url.substr(protohost.length); + removed = ''; + } + + // no more matching layers + if (idx >= stack.length) { + setImmediate(done, layerError); + return; + } + + // get pathname of request + var path = getPathname(req); + + if (path == null) { + return done(layerError); + } + + // find next matching layer + var layer; + var match; + var route; + + while (match !== true && idx < stack.length) { + layer = stack[idx++]; + match = matchLayer(layer, path); + route = layer.route; + + if (typeof match !== 'boolean') { + // hold on to layerError + layerError = layerError || match; + } + + if (match !== true) { + continue; + } + + if (!route) { + // process non-route handlers normally + continue; + } + + if (layerError) { + // routes do not match with a pending error + match = false; + continue; + } + + var method = req.method; + var has_method = route._handles_method(method); + + // build up automatic options response + if (!has_method && method === 'OPTIONS') { + appendMethods(options, route._options()); + } + + // don't even bother matching route + if (!has_method && method !== 'HEAD') { + match = false; + continue; + } + } + + // no match + if (match !== true) { + return done(layerError); + } + + // store route for dispatch on change + if (route) { + req.route = route; + } + + // Capture one-time layer values + req.params = self.mergeParams + ? mergeParams(layer.params, parentParams) + : layer.params; + var layerPath = layer.path; + + // this should be done for the layer + self.process_params(layer, paramcalled, req, res, function (err) { + if (err) { + return next(layerError || err); + } + + if (route) { + return layer.handle_request(req, res, next); + } + + trim_prefix(layer, layerError, layerPath, path); + }); + } + + function trim_prefix(layer, layerError, layerPath, path) { + var c = path[layerPath.length]; + if (c && '/' !== c && '.' !== c) return next(layerError); + + // Trim off the part of the url that matches the route + // middleware (.use stuff) needs to have the path stripped + if (layerPath.length !== 0) { + debug('trim prefix (%s) from url %s', layerPath, req.url); + removed = layerPath; + req.url = protohost + req.url.substr(protohost.length + removed.length); + + // Ensure leading slash + if (!fqdn && req.url[0] !== '/') { + req.url = '/' + req.url; + slashAdded = true; + } + + // Setup base URL (no trailing slash) + req.baseUrl = parentUrl + (removed[removed.length - 1] === '/' + ? removed.substring(0, removed.length - 1) + : removed); + } + + debug('%s %s : %s', layer.name, layerPath, req.originalUrl); + + if (layerError) { + layer.handle_error(layerError, req, res, next); + } else { + layer.handle_request(req, res, next); + } + } +}; + +/** + * Process any parameters for the layer. + * + * @api private + */ + +proto.process_params = function(layer, called, req, res, done) { + var params = this.params; + + // captured parameters from the layer, keys and values + var keys = layer.keys; + + // fast track + if (!keys || keys.length === 0) { + return done(); + } + + var i = 0; + var name; + var paramIndex = 0; + var key; + var paramVal; + var paramCallbacks; + var paramCalled; + + // process params in order + // param callbacks can be async + function param(err) { + if (err) { + return done(err); + } + + if (i >= keys.length ) { + return done(); + } + + paramIndex = 0; + key = keys[i++]; + + if (!key) { + return done(); + } + + name = key.name; + paramVal = req.params[name]; + paramCallbacks = params[name]; + paramCalled = called[name]; + + if (paramVal === undefined || !paramCallbacks) { + return param(); + } + + // param previously called with same value or error occurred + if (paramCalled && (paramCalled.error || paramCalled.match === paramVal)) { + // restore value + req.params[name] = paramCalled.value; + + // next param + return param(paramCalled.error); + } + + called[name] = paramCalled = { + error: null, + match: paramVal, + value: paramVal + }; + + paramCallback(); + } + + // single param callbacks + function paramCallback(err) { + var fn = paramCallbacks[paramIndex++]; + + // store updated value + paramCalled.value = req.params[key.name]; + + if (err) { + // store error + paramCalled.error = err; + param(err); + return; + } + + if (!fn) return param(); + + try { + fn(req, res, paramCallback, paramVal, key.name); + } catch (e) { + paramCallback(e); + } + } + + param(); +}; + +/** + * Use the given middleware function, with optional path, defaulting to "/". + * + * Use (like `.all`) will run for any http METHOD, but it will not add + * handlers for those methods so OPTIONS requests will not consider `.use` + * functions even if they could respond. + * + * The other difference is that _route_ path is stripped and not visible + * to the handler function. The main effect of this feature is that mounted + * handlers can operate without any code changes regardless of the "prefix" + * pathname. + * + * @api public + */ + +proto.use = function use(fn) { + var offset = 0; + var path = '/'; + + // default path to '/' + // disambiguate router.use([fn]) + if (typeof fn !== 'function') { + var arg = fn; + + while (Array.isArray(arg) && arg.length !== 0) { + arg = arg[0]; + } + + // first arg is the path + if (typeof arg !== 'function') { + offset = 1; + path = fn; + } + } + + var callbacks = utils.flatten(slice.call(arguments, offset)); + + if (callbacks.length === 0) { + throw new TypeError('Router.use() requires middleware functions'); + } + + callbacks.forEach(function (fn) { + if (typeof fn !== 'function') { + throw new TypeError('Router.use() requires middleware function but got a ' + gettype(fn)); + } + + // add the middleware + debug('use %s %s', path, fn.name || '<anonymous>'); + + var layer = new Layer(path, { + sensitive: this.caseSensitive, + strict: false, + end: false + }, fn); + + layer.route = undefined; + + this.stack.push(layer); + }, this); + + return this; +}; + +/** + * Create a new Route for the given path. + * + * Each route contains a separate middleware stack and VERB handlers. + * + * See the Route api documentation for details on adding handlers + * and middleware to routes. + * + * @param {String} path + * @return {Route} + * @api public + */ + +proto.route = function(path){ + var route = new Route(path); + + var layer = new Layer(path, { + sensitive: this.caseSensitive, + strict: this.strict, + end: true + }, route.dispatch.bind(route)); + + layer.route = route; + + this.stack.push(layer); + return route; +}; + +// create Router#VERB functions +methods.concat('all').forEach(function(method){ + proto[method] = function(path){ + var route = this.route(path) + route[method].apply(route, slice.call(arguments, 1)); + return this; + }; +}); + +// append methods to a list of methods +function appendMethods(list, addition) { + for (var i = 0; i < addition.length; i++) { + var method = addition[i]; + if (list.indexOf(method) === -1) { + list.push(method); + } + } +} + +// get pathname of request +function getPathname(req) { + try { + return parseUrl(req).pathname; + } catch (err) { + return undefined; + } +} + +// get type for error message +function gettype(obj) { + var type = typeof obj; + + if (type !== 'object') { + return type; + } + + // inspect [[Class]] for objects + return toString.call(obj) + .replace(objectRegExp, '$1'); +} + +/** + * Match path to a layer. + * + * @param {Layer} layer + * @param {string} path + * @private + */ + +function matchLayer(layer, path) { + try { + return layer.match(path); + } catch (err) { + return err; + } +} + +// merge params with parent params +function mergeParams(params, parent) { + if (typeof parent !== 'object' || !parent) { + return params; + } + + // make copy of parent for base + var obj = mixin({}, parent); + + // simple non-numeric merging + if (!(0 in params) || !(0 in parent)) { + return mixin(obj, params); + } + + var i = 0; + var o = 0; + + // determine numeric gaps + while (i === o || o in parent) { + if (i in params) i++; + if (o in parent) o++; + } + + // offset numeric indices in params before merge + for (i--; i >= 0; i--) { + params[i + o] = params[i]; + + // create holes for the merge when necessary + if (i < o) { + delete params[i]; + } + } + + return mixin(parent, params); +} + +// restore obj props after function +function restore(fn, obj) { + var props = new Array(arguments.length - 2); + var vals = new Array(arguments.length - 2); + + for (var i = 0; i < props.length; i++) { + props[i] = arguments[i + 2]; + vals[i] = obj[props[i]]; + } + + return function(err){ + // restore vals + for (var i = 0; i < props.length; i++) { + obj[props[i]] = vals[i]; + } + + return fn.apply(this, arguments); + }; +} + +// send an OPTIONS response +function sendOptionsResponse(res, options, next) { + try { + var body = options.join(','); + res.set('Allow', body); + res.send(body); + } catch (err) { + next(err); + } +} + +// wrap a function +function wrap(old, fn) { + return function proxy() { + var args = new Array(arguments.length + 1); + + args[0] = old; + for (var i = 0, len = arguments.length; i < len; i++) { + args[i + 1] = arguments[i]; + } + + fn.apply(this, args); + }; +} diff --git a/dgbuilder/dgeflows/node_modules/express/lib/router/layer.js b/dgbuilder/dgeflows/node_modules/express/lib/router/layer.js new file mode 100644 index 00000000..88ebd396 --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/router/layer.js @@ -0,0 +1,166 @@ +/** + * Module dependencies. + */ + +var pathRegexp = require('path-to-regexp'); +var debug = require('debug')('express:router:layer'); + +/** + * Module variables. + */ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * Expose `Layer`. + */ + +module.exports = Layer; + +function Layer(path, options, fn) { + if (!(this instanceof Layer)) { + return new Layer(path, options, fn); + } + + debug('new %s', path); + options = options || {}; + + this.handle = fn; + this.name = fn.name || '<anonymous>'; + this.params = undefined; + this.path = undefined; + this.regexp = pathRegexp(path, this.keys = [], options); + + if (path === '/' && options.end === false) { + this.regexp.fast_slash = true; + } +} + +/** + * Handle the error for the layer. + * + * @param {Error} error + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handle_error = function handle_error(error, req, res, next) { + var fn = this.handle; + + if (fn.length !== 4) { + // not a standard error handler + return next(error); + } + + try { + fn(error, req, res, next); + } catch (err) { + next(err); + } +}; + +/** + * Handle the request for the layer. + * + * @param {Request} req + * @param {Response} res + * @param {function} next + * @api private + */ + +Layer.prototype.handle_request = function handle(req, res, next) { + var fn = this.handle; + + if (fn.length > 3) { + // not a standard request handler + return next(); + } + + try { + fn(req, res, next); + } catch (err) { + next(err); + } +}; + +/** + * Check if this route matches `path`, if so + * populate `.params`. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +Layer.prototype.match = function match(path) { + if (path == null) { + // no path, nothing matches + this.params = undefined; + this.path = undefined; + return false; + } + + if (this.regexp.fast_slash) { + // fast path non-ending match for / (everything matches) + this.params = {}; + this.path = ''; + return true; + } + + var m = this.regexp.exec(path); + + if (!m) { + this.params = undefined; + this.path = undefined; + return false; + } + + // store values + this.params = {}; + this.path = m[0]; + + var keys = this.keys; + var params = this.params; + var prop; + var n = 0; + var key; + var val; + + for (var i = 1, len = m.length; i < len; ++i) { + key = keys[i - 1]; + prop = key + ? key.name + : n++; + val = decode_param(m[i]); + + if (val !== undefined || !(hasOwnProperty.call(params, prop))) { + params[prop] = val; + } + } + + return true; +}; + +/** + * Decode param value. + * + * @param {string} val + * @return {string} + * @api private + */ + +function decode_param(val){ + if (typeof val !== 'string') { + return val; + } + + try { + return decodeURIComponent(val); + } catch (e) { + var err = new TypeError("Failed to decode param '" + val + "'"); + err.status = 400; + throw err; + } +} diff --git a/dgbuilder/dgeflows/node_modules/express/lib/router/route.js b/dgbuilder/dgeflows/node_modules/express/lib/router/route.js new file mode 100644 index 00000000..6213b821 --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/router/route.js @@ -0,0 +1,183 @@ +/** + * Module dependencies. + */ + +var debug = require('debug')('express:router:route'); +var Layer = require('./layer'); +var methods = require('methods'); +var utils = require('../utils'); + +/** + * Expose `Route`. + */ + +module.exports = Route; + +/** + * Initialize `Route` with the given `path`, + * + * @param {String} path + * @api private + */ + +function Route(path) { + debug('new %s', path); + this.path = path; + this.stack = []; + + // route handlers for various http methods + this.methods = {}; +} + +/** + * @api private + */ + +Route.prototype._handles_method = function _handles_method(method) { + if (this.methods._all) { + return true; + } + + method = method.toLowerCase(); + + if (method === 'head' && !this.methods['head']) { + method = 'get'; + } + + return Boolean(this.methods[method]); +}; + +/** + * @return {Array} supported HTTP methods + * @api private + */ + +Route.prototype._options = function _options() { + var methods = Object.keys(this.methods); + + // append automatic head + if (this.methods.get && !this.methods.head) { + methods.push('head'); + } + + for (var i = 0; i < methods.length; i++) { + // make upper case + methods[i] = methods[i].toUpperCase(); + } + + return methods; +}; + +/** + * dispatch req, res into this route + * + * @api private + */ + +Route.prototype.dispatch = function(req, res, done){ + var idx = 0; + var stack = this.stack; + if (stack.length === 0) { + return done(); + } + + var method = req.method.toLowerCase(); + if (method === 'head' && !this.methods['head']) { + method = 'get'; + } + + req.route = this; + + next(); + + function next(err) { + if (err && err === 'route') { + return done(); + } + + var layer = stack[idx++]; + if (!layer) { + return done(err); + } + + if (layer.method && layer.method !== method) { + return next(err); + } + + if (err) { + layer.handle_error(err, req, res, next); + } else { + layer.handle_request(req, res, next); + } + } +}; + +/** + * Add a handler for all HTTP verbs to this route. + * + * Behaves just like middleware and can respond or call `next` + * to continue processing. + * + * You can use multiple `.all` call to add multiple handlers. + * + * function check_something(req, res, next){ + * next(); + * }; + * + * function validate_user(req, res, next){ + * next(); + * }; + * + * route + * .all(validate_user) + * .all(check_something) + * .get(function(req, res, next){ + * res.send('hello world'); + * }); + * + * @param {function} handler + * @return {Route} for chaining + * @api public + */ + +Route.prototype.all = function(){ + var callbacks = utils.flatten([].slice.call(arguments)); + callbacks.forEach(function(fn) { + if (typeof fn !== 'function') { + var type = {}.toString.call(fn); + var msg = 'Route.all() requires callback functions but got a ' + type; + throw new Error(msg); + } + + var layer = Layer('/', {}, fn); + layer.method = undefined; + + this.methods._all = true; + this.stack.push(layer); + }, this); + + return this; +}; + +methods.forEach(function(method){ + Route.prototype[method] = function(){ + var callbacks = utils.flatten([].slice.call(arguments)); + + callbacks.forEach(function(fn) { + if (typeof fn !== 'function') { + var type = {}.toString.call(fn); + var msg = 'Route.' + method + '() requires callback functions but got a ' + type; + throw new Error(msg); + } + + debug('%s %s', method, this.path); + + var layer = Layer('/', {}, fn); + layer.method = method; + + this.methods[method] = true; + this.stack.push(layer); + }, this); + return this; + }; +}); diff --git a/dgbuilder/dgeflows/node_modules/express/lib/utils.js b/dgbuilder/dgeflows/node_modules/express/lib/utils.js new file mode 100644 index 00000000..9c004cc7 --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/utils.js @@ -0,0 +1,283 @@ +/** + * Module dependencies. + */ + +var contentDisposition = require('content-disposition'); +var deprecate = require('depd')('express'); +var mime = require('send').mime; +var basename = require('path').basename; +var etag = require('etag'); +var proxyaddr = require('proxy-addr'); +var qs = require('qs'); +var querystring = require('querystring'); +var typer = require('media-typer'); + +/** + * Return strong ETag for `body`. + * + * @param {String|Buffer} body + * @param {String} [encoding] + * @return {String} + * @api private + */ + +exports.etag = function (body, encoding) { + var buf = !Buffer.isBuffer(body) + ? new Buffer(body, encoding) + : body; + + return etag(buf, {weak: false}); +}; + +/** + * Return weak ETag for `body`. + * + * @param {String|Buffer} body + * @param {String} [encoding] + * @return {String} + * @api private + */ + +exports.wetag = function wetag(body, encoding){ + var buf = !Buffer.isBuffer(body) + ? new Buffer(body, encoding) + : body; + + return etag(buf, {weak: true}); +}; + +/** + * Check if `path` looks absolute. + * + * @param {String} path + * @return {Boolean} + * @api private + */ + +exports.isAbsolute = function(path){ + if ('/' == path[0]) return true; + if (':' == path[1] && '\\' == path[2]) return true; + if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path +}; + +/** + * Flatten the given `arr`. + * + * @param {Array} arr + * @return {Array} + * @api private + */ + +exports.flatten = function(arr, ret){ + ret = ret || []; + var len = arr.length; + for (var i = 0; i < len; ++i) { + if (Array.isArray(arr[i])) { + exports.flatten(arr[i], ret); + } else { + ret.push(arr[i]); + } + } + return ret; +}; + +/** + * Normalize the given `type`, for example "html" becomes "text/html". + * + * @param {String} type + * @return {Object} + * @api private + */ + +exports.normalizeType = function(type){ + return ~type.indexOf('/') + ? acceptParams(type) + : { value: mime.lookup(type), params: {} }; +}; + +/** + * Normalize `types`, for example "html" becomes "text/html". + * + * @param {Array} types + * @return {Array} + * @api private + */ + +exports.normalizeTypes = function(types){ + var ret = []; + + for (var i = 0; i < types.length; ++i) { + ret.push(exports.normalizeType(types[i])); + } + + return ret; +}; + +/** + * Generate Content-Disposition header appropriate for the filename. + * non-ascii filenames are urlencoded and a filename* parameter is added + * + * @param {String} filename + * @return {String} + * @api private + */ + +exports.contentDisposition = deprecate.function(contentDisposition, + 'utils.contentDisposition: use content-disposition npm module instead'); + +/** + * Parse accept params `str` returning an + * object with `.value`, `.quality` and `.params`. + * also includes `.originalIndex` for stable sorting + * + * @param {String} str + * @return {Object} + * @api private + */ + +function acceptParams(str, index) { + var parts = str.split(/ *; */); + var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index }; + + for (var i = 1; i < parts.length; ++i) { + var pms = parts[i].split(/ *= */); + if ('q' == pms[0]) { + ret.quality = parseFloat(pms[1]); + } else { + ret.params[pms[0]] = pms[1]; + } + } + + return ret; +} + +/** + * Compile "etag" value to function. + * + * @param {Boolean|String|Function} val + * @return {Function} + * @api private + */ + +exports.compileETag = function(val) { + var fn; + + if (typeof val === 'function') { + return val; + } + + switch (val) { + case true: + fn = exports.wetag; + break; + case false: + break; + case 'strong': + fn = exports.etag; + break; + case 'weak': + fn = exports.wetag; + break; + default: + throw new TypeError('unknown value for etag function: ' + val); + } + + return fn; +} + +/** + * Compile "query parser" value to function. + * + * @param {String|Function} val + * @return {Function} + * @api private + */ + +exports.compileQueryParser = function compileQueryParser(val) { + var fn; + + if (typeof val === 'function') { + return val; + } + + switch (val) { + case true: + fn = querystring.parse; + break; + case false: + fn = newObject; + break; + case 'extended': + fn = qs.parse; + break; + case 'simple': + fn = querystring.parse; + break; + default: + throw new TypeError('unknown value for query parser function: ' + val); + } + + return fn; +} + +/** + * Compile "proxy trust" value to function. + * + * @param {Boolean|String|Number|Array|Function} val + * @return {Function} + * @api private + */ + +exports.compileTrust = function(val) { + if (typeof val === 'function') return val; + + if (val === true) { + // Support plain true/false + return function(){ return true }; + } + + if (typeof val === 'number') { + // Support trusting hop count + return function(a, i){ return i < val }; + } + + if (typeof val === 'string') { + // Support comma-separated values + val = val.split(/ *, */); + } + + return proxyaddr.compile(val || []); +} + +/** + * Set the charset in a given Content-Type string. + * + * @param {String} type + * @param {String} charset + * @return {String} + * @api private + */ + +exports.setCharset = function(type, charset){ + if (!type || !charset) return type; + + // parse type + var parsed = typer.parse(type); + + // set charset + parsed.parameters.charset = charset; + + // format type + return typer.format(parsed); +}; + +/** + * Return new empty object. + * + * @return {Object} + * @api private + */ + +function newObject() { + return {}; +} diff --git a/dgbuilder/dgeflows/node_modules/express/lib/view.js b/dgbuilder/dgeflows/node_modules/express/lib/view.js new file mode 100644 index 00000000..e0989b4d --- /dev/null +++ b/dgbuilder/dgeflows/node_modules/express/lib/view.js @@ -0,0 +1,142 @@ +/** + * Module dependencies. + */ + +var debug = require('debug')('express:view'); +var path = require('path'); +var fs = require('fs'); +var utils = require('./utils'); + +/** + * Module variables. + * @private + */ + +var dirname = path.dirname; +var basename = path.basename; +var extname = path.extname; +var join = path.join; +var resolve = path.resolve; + +/** + * Expose `View`. + */ + +module.exports = View; + +/** + * Initialize a new `View` with the given `name`. + * + * Options: + * + * - `defaultEngine` the default template engine name + * - `engines` template engine require() cache + * - `root` root path for view lookup + * + * @param {String} name + * @param {Object} options + * @api private + */ + +function View(name, options) { + options = options || {}; + this.name = name; + this.root = options.root; + var engines = options.engines; + this.defaultEngine = options.defaultEngine; + var ext = this.ext = extname(name); + if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.'); + if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine); + this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express); + this.path = this.lookup(name); +} + +/** + * Lookup view by the given `name` + * + * @param {String} name + * @return {String} + * @api private + */ + +View.prototype.lookup = function lookup(name) { + var path; + var roots = [].concat(this.root); + + debug('lookup "%s"', name); + + for (var i = 0; i < roots.length && !path; i++) { + var root = roots[i]; + + // resolve the path + var loc = resolve(root, name); + var dir = dirname(loc); + var file = basename(loc); + + // resolve the file + path = this.resolve(dir, file); + } + + return path; +}; + +/** + * Render with the given `options` and callback `fn(err, str)`. + * + * @param {Object} options + * @param {Function} fn + * @api private + */ + +View.prototype.render = function render(options, fn) { + debug('render "%s"', this.path); + this.engine(this.path, options, fn); +}; + +/** + * Resolve the file within the given directory. + * + * @param {string} dir + * @param {string} file + * @private + */ + +View.prototype.resolve = function resolve(dir, file) { + var ext = this.ext; + var path; + var stat; + + // <path>.<ext> + path = join(dir, file); + stat = tryStat(path); + + if (stat && stat.isFile()) { + return path; + } + + // <path>/index.<ext> + path = join(dir, basename(file, ext), 'index' + ext); + stat = tryStat(path); + + if (stat && stat.isFile()) { + return path; + } +}; + +/** + * Return a stat, maybe. + * + * @param {string} path + * @return {fs.Stats} + * @private + */ + +function tryStat(path) { + debug('stat "%s"', path); + + try { + return fs.statSync(path); + } catch (e) { + return undefined; + } +} |