some html
'); * 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; var head = 'HEAD' == req.method; var len; // settings var app = this.app; // 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.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 (app.settings.etag && len && 'GET' == req.method) { 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.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.set('Content-Type', 'application/json'); // jsonp if (callback) { if (Array.isArray(callback)) callback = callback[0]; this.set('Content-Type', 'text/javascript'); var cb = callback.replace(/[^\[\]\w$.]/g, ''); body = 'typeof ' + cb + ' === \'function\' && ' + 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 * - `hidden` serve hidden files, defaulting to false * * 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.'); * } * }); * }); * * @param {String} path * @param {Object|Function} options or fn * @param {Function} fn * @api public */ res.sendfile = function(path, options, fn){ options = options || {}; var self = this; var req = self.req; var next = this.req.next; var done; // support function as second arg if ('function' == typeof options) { fn = options; options = {}; } // socket errors req.socket.on('error', error); // errors function error(err) { if (done) return; done = true; // clean up cleanup(); if (!self.headersSent) self.removeHeader('Content-Disposition'); // callback available if (fn) return fn(err); // list in limbo if there's no callback if (self.headersSent) return; // delegate next(err); } // streaming function stream(stream) { if (done) return; cleanup(); if (fn) stream.on('end', fn); } // cleanup function cleanup() { req.socket.removeListener('error', error); } // Back-compat options.maxage = options.maxage || options.maxAge || 0; // transfer var file = send(req, path, options); file.on('error', error); file.on('directory', next); file.on('stream', stream); file.pipe(this); this.on('finish', cleanup); }; /** * Transfer the file at the given `path` as an attachment. * * Optionally providing an alternate attachment `filename`, * and optional callback `fn(err)`. The callback is invoked * when the data transfer is complete, or when an error has * ocurred. Be sure to check `res.headersSent` if you plan to respond. * * This method uses `res.sendfile()`. * * @param {String} path * @param {String|Function} filename or fn * @param {Function} fn * @api public */ res.download = function(path, filename, fn){ // support function as second arg if ('function' == typeof filename) { fn = filename; filename = null; } filename = filename || path; this.set('Content-Disposition', contentDisposition(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('hey
'); * }, * * '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('hey
'); * }, * * 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(filename){ if (filename) this.type(extname(filename)); this.set('Content-Disposition', contentDisposition(filename)); return this; }; /** * Set header `field` to `val`, or pass * an object of header fields. * * Examples: * * res.set('Foo', ['bar', 'baz']); * res.set('Accept', 'application/json'); * res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' }); * * Aliased as `res.header()`. * * @param {String|Object|Array} field * @param {String} val * @return {ServerResponse} for chaining * @api public */ res.set = res.header = function(field, val){ if (2 == arguments.length) { if (Array.isArray(val)) val = val.map(String); else val = String(val); 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 * @param {ServerResponse} for chaining * @api public */ res.clearCookie = function(name, options){ var opts = { expires: new Date(1), path: '/' }; return this.cookie(name, '', options ? mixin(opts, options) : opts); }; /** * Set cookie `name` to `val`, with the given `options`. * * Options: * * - `maxAge` max-age in milliseconds, converted to `expires` * - `signed` sign the cookie * - `path` defaults to "/" * * Examples: * * // "Remember Me" for 15 minutes * res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); * * // save as above * res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) * * @param {String} name * @param {String|Object} val * @param {Options} options * @api public */ res.cookie = function(name, val, options){ options = mixin({}, 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 * @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('http://example.com', 301); * res.redirect('../login'); // /blog/post/1 -> /blog/login * * @param {String} url * @param {Number} code * @api public */ res.redirect = function(url){ var head = 'HEAD' == this.req.method; var status = 302; var body; // allow status / url if (2 == arguments.length) { if ('number' == typeof url) { status = url; url = arguments[1]; } else { status = arguments[1]; } } // Set location header this.location(url); url = this.get('Location'); // Support text/{plain,html} by default this.format({ text: function(){ body = statusCodes[status] + '. Redirecting to ' + encodeURI(url); }, html: function(){ var u = escapeHtml(url); body = '' + statusCodes[status] + '. Redirecting to ' + u + '
'; }, default: function(){ body = ''; } }); // Respond this.statusCode = status; this.set('Content-Length', Buffer.byteLength(body)); this.end(head ? null : body); }; /** * Add `field` to Vary. If already present in the Vary set, then * this call is simply ignored. * * @param {Array|String} field * @param {ServerResponse} for chaining * @api public */ res.vary = function(field){ var self = this; // nothing if (!field) return this; // array if (Array.isArray(field)) { field.forEach(function(field){ self.vary(field); }); return; } var vary = this.get('Vary'); // append if (vary) { vary = vary.split(/ *, */); if (!~vary.indexOf(field)) vary.push(field); this.set('Vary', vary.join(', ')); return this; } // set this.set('Vary', 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 * * @param {String} view * @param {Object|Function} options or callback function * @param {Function} fn * @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); }; 4.1.1~dfsg/lib/utils.js 0000644 0000000 0000000 00000005406 12327313561 013533 0 ustar root root /** * Module dependencies. */ var mime = require('send').mime; var crc32 = require('buffer-crc32'); var basename = require('path').basename; /** * Return ETag for `body`. * * @param {String|Buffer} body * @return {String} * @api private */ exports.etag = function(body){ return '"' + crc32.signed(body) + '"'; }; /** * 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 = function(filename){ var ret = 'attachment'; if (filename) { filename = basename(filename); // if filename contains non-ascii characters, add a utf-8 version ala RFC 5987 ret = /[^\040-\176]/.test(filename) ? 'attachment; filename=' + encodeURI(filename) + '; filename*=UTF-8\'\'' + encodeURI(filename) : 'attachment; filename="' + filename + '"'; } return ret; }; /** * 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; } 4.1.1~dfsg/lib/express.js 0000644 0000000 0000000 00000003331 12327313561 014057 0 ustar root root /** * Module dependencies. */ var EventEmitter = require('events').EventEmitter; var mixin = require('utils-merge'); 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 }); }); 4.1.1~dfsg/lib/router/ 0000755 0000000 0000000 00000000000 12327313561 013350 5 ustar root root 4.1.1~dfsg/lib/router/route.js 0000644 0000000 0000000 00000007312 12327313561 015047 0 ustar root root /** * Module dependencies. */ var debug = require('debug')('express:router:route'); 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 = undefined; // route handlers for various http methods this.methods = {}; } /** * @return {Array} supported HTTP methods * @api private */ Route.prototype._options = function(){ return Object.keys(this.methods).map(function(method) { return method.toUpperCase(); }); }; /** * dispatch req, res into this route * * @api private */ Route.prototype.dispatch = function(req, res, done){ var self = this; var method = req.method.toLowerCase(); if (method === 'head' && !this.methods['head']) { method = 'get'; } req.route = self; // single middleware route case if (typeof this.stack === 'function') { this.stack(req, res, done); return; } var stack = self.stack; if (!stack) { return done(); } var idx = 0; (function next_layer(err) { if (err && err === 'route') { return done(); } var layer = stack[idx++]; if (!layer) { return done(err); } if (layer.method && layer.method !== method) { return next_layer(err); } var arity = layer.handle.length; if (err) { if (arity < 4) { return next_layer(err); } try { layer.handle(err, req, res, next_layer); } catch (err) { next_layer(err); } return; } if (arity > 3) { return next_layer(); } try { layer.handle(req, res, next_layer); } catch (err) { next_layer(err); } })(); }; /** * 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 self = this; 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); } if (!self.stack) { self.stack = fn; } else if (typeof self.stack === 'function') { self.stack = [{ handle: self.stack }, { handle: fn }]; } else { self.stack.push({ handle: fn }); } }); return self; }; methods.forEach(function(method){ Route.prototype[method] = function(){ var self = this; 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, self.path); if (!self.methods[method]) { self.methods[method] = true; } if (!self.stack) { self.stack = []; } else if (typeof self.stack === 'function') { self.stack = [{ handle: self.stack }]; } self.stack.push({ method: method, handle: fn }); }); return self; }; }); 4.1.1~dfsg/lib/router/layer.js 0000644 0000000 0000000 00000002265 12327313561 015027 0 ustar root root /** * Module dependencies. */ var pathRegexp = require('path-to-regexp'); var debug = require('debug')('express:router:layer'); /** * 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.regexp = pathRegexp(path, this.keys = [], options); this.handle = fn; } /** * Check if this route matches `path`, if so * populate `.params`. * * @param {String} path * @return {Boolean} * @api private */ Layer.prototype.match = function(path){ var keys = this.keys; var params = this.params = {}; var m = this.regexp.exec(path); var n = 0; var key; var val; if (!m) return false; this.path = m[0]; for (var i = 1, len = m.length; i < len; ++i) { key = keys[i - 1]; try { val = 'string' == typeof m[i] ? decodeURIComponent(m[i]) : m[i]; } catch(e) { var err = new Error("Failed to decode param '" + m[i] + "'"); err.status = 400; throw err; } if (key) { params[key.name] = val; } else { params[n++] = val; } } return true; }; 4.1.1~dfsg/lib/router/index.js 0000644 0000000 0000000 00000021524 12327313561 015021 0 ustar root root /** * Module dependencies. */ var Route = require('./route'); var Layer = require('./layer'); var methods = require('methods'); var debug = require('debug')('express:router'); var parseUrl = require('parseurl'); /** * 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.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(name, fn){ // param logic if ('function' == typeof name) { this._params.push(name); return; } // apply param functions var params = this._params; var len = params.length; var ret; if (name[0] === ':') { 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 method = req.method.toLowerCase(); var search = 1 + req.url.indexOf('?'); var pathlength = search ? search - 1 : req.url.length; var fqdn = 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; // store options for OPTIONS request // only used if OPTIONS request var options = []; // middleware and routes var stack = self.stack; // for options requests, respond with a default if nothing else responds if (method === 'options') { var old = done; done = function(err) { if (err || options.length === 0) return old(err); var body = options.join(','); return res.set('Allow', body).send(body); }; } (function next(err) { if (err === 'route') { err = undefined; } var layer = stack[idx++]; if (!layer) { return done(err); } if (slashAdded) { req.url = req.url.substr(1); slashAdded = false; } req.url = protohost + removed + req.url.substr(protohost.length); req.originalUrl = req.originalUrl || req.url; removed = ''; try { var path = parseUrl(req).pathname; if (undefined == path) path = '/'; if (!layer.match(path)) return next(err); // route object and not middleware var route = layer.route; // if final route, then we support options if (route) { // we don't run any routes with error first if (err) { return next(err); } req.route = route; // we can now dispatch to the route if (method === 'options' && !route.methods['options']) { options.push.apply(options, route._options()); } } req.params = layer.params; // this should be done for the layer return self.process_params(layer, req, res, function(err) { if (err) { return next(err); } if (route) { return layer.handle(req, res, next); } trim_prefix(); }); } catch (err) { next(err); } function trim_prefix() { var c = path[layer.path.length]; if (c && '/' != c && '.' != c) return next(err); // Trim off the part of the url that matches the route // middleware (.use stuff) needs to have the path stripped debug('trim prefix (%s) from url %s', removed, req.url); removed = layer.path; req.url = protohost + req.url.substr(protohost.length + removed.length); // Ensure leading slash if (!fqdn && '/' != req.url[0]) { req.url = '/' + req.url; slashAdded = true; } debug('%s %s : %s', layer.handle.name || 'anonymous', layer.path, req.originalUrl); var arity = layer.handle.length; if (err) { if (arity === 4) { layer.handle(err, req, res, next); } else { next(err); } } else if (arity < 4) { layer.handle(req, res, next); } else { next(err); } } })(); }; /** * Process any parameters for the route. * * @api private */ proto.process_params = function(route, req, res, done) { var params = this.params; // captured parameters from the route, keys and values var keys = route.keys; // fast track if (!keys || keys.length === 0) { return done(); } var i = 0; var paramIndex = 0; var key; var paramVal; var paramCallbacks; // 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++]; paramVal = key && req.params[key.name]; paramCallbacks = key && params[key.name]; try { if (paramCallbacks && undefined !== paramVal) { return paramCallback(); } else if (key) { return param(); } } catch (err) { return done(err); } done(); } // single param callbacks function paramCallback(err) { var fn = paramCallbacks[paramIndex++]; if (err || !fn) return param(err); fn(req, res, paramCallback, paramVal, key.name); } 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. * * @param {String|Function} route * @param {Function} fn * @return {app} for chaining * @api public */ proto.use = function(route, fn){ // default route to '/' if ('string' != typeof route) { fn = route; route = '/'; } if (typeof fn !== 'function') { var type = {}.toString.call(fn); var msg = 'Router.use() requires callback functions but got a ' + type; throw new Error(msg); } // strip trailing slash if ('/' == route[route.length - 1]) { route = route.slice(0, -1); } var layer = new Layer(route, { sensitive: this.caseSensitive, strict: this.strict, end: false }, fn); // add the middleware debug('use %s %s', route || '/', fn.name || 'anonymous'); this.stack.push(layer); 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; }; }); 4.1.1~dfsg/lib/middleware/ 0000755 0000000 0000000 00000000000 12327313561 014145 5 ustar root root 4.1.1~dfsg/lib/middleware/init.js 0000644 0000000 0000000 00000001072 12327313561 015446 0 ustar root root /** * 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){ 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(); }; }; 4.1.1~dfsg/lib/middleware/query.js 0000644 0000000 0000000 00000001416 12327313561 015652 0 ustar root root /** * Module dependencies. */ var qs = require('qs'); var parseUrl = require('parseurl'); /** * Query: * * Automatically parse the query-string when available, * populating the `req.query` object using * [qs](https://github.com/visionmedia/node-querystring). * * Examples: * * .use(connect.query()) * .use(function(req, res){ * res.end(JSON.stringify(req.query)); * }); * * The `options` passed are provided to qs.parse function. * * @param {Object} options * @return {Function} * @api public */ module.exports = function query(options){ return function query(req, res, next){ if (!req.query) { req.query = ~req.url.indexOf('?') ? qs.parse(parseUrl(req).query, options) : {}; } next(); }; }; 4.1.1~dfsg/package.json 0000644 0000000 0000000 00000003634 12327313561 013556 0 ustar root root { "name": "express", "description": "Sinatra inspired web development framework", "version": "4.1.1", "author": "TJ Holowaychuktobi
', done); }) it('should support absolute paths with "view engine"', function(done){ var app = express(); app.locals.user = { name: 'tobi' }; app.set('view engine', 'jade'); app.use(function(req, res){ res.render(__dirname + '/fixtures/user'); }); request(app) .get('/') .expect('tobi
', done); }) it('should expose app.locals', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.locals.user = { name: 'tobi' }; app.use(function(req, res){ res.render('user.jade'); }); request(app) .get('/') .expect('tobi
', done); }) it('should expose app.locals with `name` property', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.locals.name = 'tobi'; app.use(function(req, res){ res.render('name.jade'); }); request(app) .get('/') .expect('tobi
', done); }) it('should support index.This is an email
', done); }) }) }) describe('.render(name, option)', function(){ it('should render the template', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); var user = { name: 'tobi' }; app.use(function(req, res){ res.render('user.jade', { user: user }); }); request(app) .get('/') .expect('tobi
', done); }) it('should expose app.locals', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.locals.user = { name: 'tobi' }; app.use(function(req, res){ res.render('user.jade'); }); request(app) .get('/') .expect('tobi
', done); }) it('should expose res.locals', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.use(function(req, res){ res.locals.user = { name: 'tobi' }; res.render('user.jade'); }); request(app) .get('/') .expect('tobi
', done); }) it('should give precedence to res.locals over app.locals', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.locals.user = { name: 'tobi' }; app.use(function(req, res){ res.locals.user = { name: 'jane' }; res.render('user.jade', {}); }); request(app) .get('/') .expect('jane
', done); }) it('should give precedence to res.render() locals over res.locals', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); var jane = { name: 'jane' }; app.use(function(req, res){ res.locals.user = { name: 'tobi' }; res.render('user.jade', { user: jane }); }); request(app) .get('/') .expect('jane
', done); }) it('should give precedence to res.render() locals over app.locals', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.locals.user = { name: 'tobi' }; var jane = { name: 'jane' }; app.use(function(req, res){ res.render('user.jade', { user: jane }); }); request(app) .get('/') .expect('jane
', done); }) }) describe('.render(name, options, fn)', function(){ it('should pass the resulting string', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.use(function(req, res){ var tobi = { name: 'tobi' }; res.render('user.jade', { user: tobi }, function(err, html){ html = html.replace('tobi', 'loki'); res.end(html); }); }); request(app) .get('/') .expect('loki
', done); }) }) describe('.render(name, fn)', function(){ it('should pass the resulting string', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.use(function(req, res){ res.locals.user = { name: 'tobi' }; res.render('user.jade', function(err, html){ html = html.replace('tobi', 'loki'); res.end(html); }); }); request(app) .get('/') .expect('loki
', done); }) describe('when an error occurs', function(){ it('should pass it to the callback', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.use(function(req, res){ res.render('user.jade', function(err){ res.end(err.message); }); }); request(app) .get('/') .expect(/Cannot read property '[^']+' of undefined/, done); }) }) }) }) 4.1.1~dfsg/test/req.get.js 0000644 0000000 0000000 00000001477 12327313561 014155 0 ustar root root var express = require('../') , request = require('supertest') , assert = require('assert'); describe('req', function(){ describe('.get(field)', function(){ it('should return the header field value', function(done){ var app = express(); app.use(function(req, res){ assert(req.get('Something-Else') === undefined); res.end(req.get('Content-Type')); }); request(app) .post('/') .set('Content-Type', 'application/json') .expect('application/json', done); }) it('should special-case Referer', function(done){ var app = express(); app.use(function(req, res){ res.end(req.get('Referer')); }); request(app) .post('/') .set('Referrer', 'http://foobar.com') .expect('http://foobar.com', done); }) }) }) 4.1.1~dfsg/test/req.signedCookies.js 0000644 0000000 0000000 00000001654 12327313561 016161 0 ustar root root var express = require('../') , request = require('supertest') , cookieParser = require('cookie-parser') describe('req', function(){ describe('.signedCookies', function(){ it('should return a signed JSON cookie', function(done){ var app = express(); app.use(cookieParser('secret')); app.use(function(req, res){ if ('/set' == req.path) { res.cookie('obj', { foo: 'bar' }, { signed: true }); res.end(); } else { res.send(req.signedCookies); } }); request(app) .get('/set') .end(function(err, res){ if (err) return done(err); var cookie = res.header['set-cookie']; request(app) .get('/') .set('Cookie', cookie) .end(function(err, res){ if (err) return don(err); res.body.should.eql({ obj: { foo: 'bar' } }); done(); }); }); }) }) }) 4.1.1~dfsg/test/res.clearCookie.js 0000644 0000000 0000000 00000001767 12327313561 015622 0 ustar root root var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.clearCookie(name)', function(){ it('should set a cookie passed expiry', function(done){ var app = express(); app.use(function(req, res){ res.clearCookie('sid').end(); }); request(app) .get('/') .end(function(err, res){ var val = 'sid=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT'; res.header['set-cookie'].should.eql([val]); done(); }) }) }) describe('.clearCookie(name, options)', function(){ it('should set the given params', function(done){ var app = express(); app.use(function(req, res){ res.clearCookie('sid', { path: '/admin' }).end(); }); request(app) .get('/') .end(function(err, res){ var val = 'sid=; Path=/admin; Expires=Thu, 01 Jan 1970 00:00:00 GMT'; res.header['set-cookie'].should.eql([val]); done(); }) }) }) }) 4.1.1~dfsg/test/app.all.js 0000644 0000000 0000000 00000001252 12327313561 014126 0 ustar root root var express = require('../') , request = require('supertest'); describe('app.all()', function(){ it('should add a router per method', function(done){ var app = express(); app.all('/tobi', function(req, res){ res.end(req.method); }); request(app) .put('/tobi') .expect('PUT', function(){ request(app) .get('/tobi') .expect('GET', done); }); }) it('should ', function(done){ var app = express() , n = 0; app.all('/*', function(req, res, next){ if (n++) return done(new Error('DELETE called several times')); next(); }); request(app) .del('/tobi') .expect(404, done); }) }) 4.1.1~dfsg/test/res.sendfile.js 0000644 0000000 0000000 00000014740 12327313561 015166 0 ustar root root var express = require('../') , request = require('supertest') , assert = require('assert'); describe('res', function(){ describe('.sendfile(path, fn)', function(){ it('should invoke the callback when complete', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('test/fixtures/user.html', function(err){ assert(!err); req.socket.listeners('error').should.have.length(1); // node's original handler done(); }); }); request(app) .get('/') .expect(200) .end(function(){}); }) it('should utilize the same options as express.static()', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('test/fixtures/user.html', { maxAge: 60000 }); }); request(app) .get('/') .expect('Cache-Control', 'public, max-age=60') .end(done); }) it('should invoke the callback on 404', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.sendfile('test/fixtures/nope.html', function(err){ ++calls; assert(!res.headersSent); res.send(err.message); }); }); request(app) .get('/') .end(function(err, res){ assert(1 == calls, 'called too many times'); res.text.should.startWith("ENOENT, stat"); res.statusCode.should.equal(200); done(); }); }) it('should not override manual content-types', function(done){ var app = express(); app.use(function(req, res){ res.contentType('txt'); res.sendfile('test/fixtures/user.html'); }); request(app) .get('/') .expect('Content-Type', 'text/plain; charset=utf-8') .end(done); }) it('should invoke the callback on 403', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.sendfile('test/fixtures/foo/../user.html', function(err){ assert(!res.headersSent); ++calls; res.send(err.message); }); }); request(app) .get('/') .expect('Forbidden') .expect(200, done); }) it('should invoke the callback on socket error', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.sendfile('test/fixtures/user.html', function(err){ assert(!res.headersSent); req.socket.listeners('error').should.have.length(1); // node's original handler done(); }); req.socket.emit('error', new Error('broken!')); }); request(app) .get('/') .end(function(){}); }) }) describe('.sendfile(path)', function(){ it('should not serve hidden files', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('test/fixtures/.name'); }); request(app) .get('/') .expect(404, done); }) it('should accept hidden option', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('test/fixtures/.name', { hidden: true }); }); request(app) .get('/') .expect(200, 'tobi', done); }) describe('with an absolute path', function(){ it('should transfer the file', function(done){ var app = express(); app.use(function(req, res){ res.sendfile(__dirname + '/fixtures/user.html'); }); request(app) .get('/') .end(function(err, res){ res.text.should.equal('{{user.name}}
'); res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); done(); }); }) }) describe('with a relative path', function(){ it('should transfer the file', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('test/fixtures/user.html'); }); request(app) .get('/') .end(function(err, res){ res.text.should.equal('{{user.name}}
'); res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); done(); }); }) it('should serve relative to "root"', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('user.html', { root: 'test/fixtures/' }); }); request(app) .get('/') .end(function(err, res){ res.text.should.equal('{{user.name}}
'); res.headers.should.have.property('content-type', 'text/html; charset=UTF-8'); done(); }); }) it('should consider ../ malicious when "root" is not set', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('test/fixtures/foo/../user.html'); }); request(app) .get('/') .expect(403, done); }) it('should allow ../ when "root" is set', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('foo/../user.html', { root: 'test/fixtures' }); }); request(app) .get('/') .expect(200, done); }) it('should disallow requesting out of "root"', function(done){ var app = express(); app.use(function(req, res){ res.sendfile('foo/../../user.html', { root: 'test/fixtures' }); }); request(app) .get('/') .expect(403, done); }) it('should next(404) when not found', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.sendfile('user.html'); }); app.use(function(req, res){ assert(0, 'this should not be called'); }); app.use(function(err, req, res, next){ ++calls; next(err); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(404); calls.should.equal(1); done(); }); }) describe('with non-GET', function(){ it('should still serve', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.sendfile(__dirname + '/fixtures/name.txt'); }); request(app) .get('/') .expect('tobi', done); }) }) }) }) }) 4.1.1~dfsg/test/req.param.js 0000644 0000000 0000000 00000002414 12327313561 014466 0 ustar root root var express = require('../') , request = require('supertest') , bodyParser = require('body-parser') describe('req', function(){ describe('.param(name, default)', function(){ it('should use the default value unless defined', function(done){ var app = express(); app.use(function(req, res){ res.end(req.param('name', 'tj')); }); request(app) .get('/') .expect('tj', done); }) }) describe('.param(name)', function(){ it('should check req.query', function(done){ var app = express(); app.use(function(req, res){ res.end(req.param('name')); }); request(app) .get('/?name=tj') .expect('tj', done); }) it('should check req.body', function(done){ var app = express(); app.use(bodyParser()); app.use(function(req, res){ res.end(req.param('name')); }); request(app) .post('/') .send({ name: 'tj' }) .expect('tj', done); }) it('should check req.params', function(done){ var app = express(); app.get('/user/:name', function(req, res){ res.end(req.param('filter') + req.param('name')); }); request(app) .get('/user/tj') .expect('undefinedtj', done); }) }) }) 4.1.1~dfsg/test/req.is.js 0000644 0000000 0000000 00000004164 12327313561 014005 0 ustar root root var express = require('../') , request = require('supertest'); function req(ct) { var req = { headers: { 'content-type': ct, 'transfer-encoding': 'chunked' }, __proto__: express.request }; return req; } describe('req.is()', function(){ it('should ignore charset', function(){ req('application/json') .is('json') .should.equal('json'); }) describe('when content-type is not present', function(){ it('should return false', function(){ req('') .is('json') .should.be.false; }) }) describe('when given an extension', function(){ it('should lookup the mime type', function(){ req('application/json') .is('json') .should.equal('json'); req('text/html') .is('json') .should.be.false; }) }) describe('when given a mime type', function(){ it('should match', function(){ req('application/json') .is('application/json') .should.equal('application/json'); req('image/jpeg') .is('application/json') .should.be.false; }) }) describe('when given */subtype', function(){ it('should match', function(){ req('application/json') .is('*/json') .should.equal('application/json'); req('image/jpeg') .is('*/json') .should.be.false; }) describe('with a charset', function(){ it('should match', function(){ req('text/html; charset=utf-8') .is('*/html') .should.equal('text/html'); req('text/plain; charset=utf-8') .is('*/html') .should.be.false; }) }) }) describe('when given type/*', function(){ it('should match', function(){ req('image/png') .is('image/*') .should.equal('image/png'); req('text/html') .is('image/*') .should.be.false; }) describe('with a charset', function(){ it('should match', function(){ req('text/html; charset=utf-8') .is('text/*') .should.equal('text/html'); req('something/html; charset=utf-8') .is('text/*') .should.be.false; }) }) }) }) 4.1.1~dfsg/test/Router.js 0000644 0000000 0000000 00000011332 12327313561 014057 0 ustar root root var express = require('../') , Router = express.Router , methods = require('methods') , assert = require('assert'); describe('Router', function(){ it('should return a function with router methods', function() { var router = Router(); assert(typeof router == 'function'); var router = new Router(); assert(typeof router == 'function'); assert(typeof router.get == 'function'); assert(typeof router.handle == 'function'); assert(typeof router.use == 'function'); }); it('should support .use of other routers', function(done){ var router = new Router(); var another = new Router(); another.get('/bar', function(req, res){ res.end(); }); router.use('/foo', another); router.handle({ url: '/foo/bar', method: 'GET' }, { end: done }); }); it('should support dynamic routes', function(done){ var router = new Router(); var another = new Router(); another.get('/:bar', function(req, res){ req.params.bar.should.equal('route'); res.end(); }); router.use('/:foo', another); router.handle({ url: '/test/route', method: 'GET' }, { end: done }); }); describe('.handle', function(){ it('should dispatch', function(done){ var router = new Router(); router.route('/foo').get(function(req, res){ res.send('foo'); }); var res = { send: function(val) { val.should.equal('foo'); done(); } } router.handle({ url: '/foo', method: 'GET' }, res); }) }) describe('.multiple callbacks', function(){ it('should throw if a callback is null', function(){ assert.throws(function () { var router = new Router(); router.route('/foo').all(null); }) }) it('should throw if a callback is undefined', function(){ assert.throws(function () { var router = new Router(); router.route('/foo').all(undefined); }) }) it('should throw if a callback is not a function', function(){ assert.throws(function () { var router = new Router(); router.route('/foo').all('not a function'); }) }) it('should not throw if all callbacks are functions', function(){ var router = new Router(); router.route('/foo').all(function(){}).all(function(){}); }) }) describe('error', function(){ it('should skip non error middleware', function(done){ var router = new Router(); router.get('/foo', function(req, res, next){ next(new Error('foo')); }); router.get('/bar', function(req, res, next){ next(new Error('bar')); }); router.use(function(req, res, next){ assert(false); }); router.use(function(err, req, res, next){ assert.equal(err.message, 'foo'); done(); }); router.handle({ url: '/foo', method: 'GET' }, {}, done); }); it('should handle throwing inside routes with params', function(done) { var router = new Router(); router.get('/foo/:id', function(req, res, next){ throw new Error('foo'); }); router.use(function(req, res, next){ assert(false); }); router.use(function(err, req, res, next){ assert.equal(err.message, 'foo'); done(); }); router.handle({ url: '/foo/2', method: 'GET' }, {}, done); }); }) describe('.all', function() { it('should support using .all to capture all http verbs', function(done){ var router = new Router(); var count = 0; router.all('/foo', function(){ count++; }); var url = '/foo?bar=baz'; methods.forEach(function testMethod(method) { router.handle({ url: url, method: method }, {}, function() {}); }); assert.equal(count, methods.length); done(); }) }) describe('.param', function() { it('should call param function when routing VERBS', function(done) { var router = new Router(); router.param('id', function(req, res, next, id) { assert.equal(id, '123'); next(); }); router.get('/foo/:id/bar', function(req, res, next) { assert.equal(req.params.id, '123'); next(); }); router.handle({ url: '/foo/123/bar', method: 'get' }, {}, done); }); it('should call param function when routing middleware', function(done) { var router = new Router(); router.param('id', function(req, res, next, id) { assert.equal(id, '123'); next(); }); router.use('/foo/:id/bar', function(req, res, next) { assert.equal(req.params.id, '123'); assert.equal(req.url, '/baz'); next(); }); router.handle({ url: '/foo/123/bar/baz', method: 'get' }, {}, done); }); }); }) 4.1.1~dfsg/test/req.route.js 0000644 0000000 0000000 00000001100 12327313561 014513 0 ustar root root var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.route', function(){ it('should be the executed Route', function(done){ var app = express(); app.get('/user/:id/:op?', function(req, res, next){ req.route.path.should.equal('/user/:id/:op?'); next(); }); app.get('/user/:id/edit', function(req, res){ req.route.path.should.equal('/user/:id/edit'); res.end(); }); request(app) .get('/user/12/edit') .expect(200, done); }) }) }) 4.1.1~dfsg/test/res.status.js 0000644 0000000 0000000 00000000633 12327313561 014714 0 ustar root root var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.status(code)', function(){ it('should set the response .statusCode', function(done){ var app = express(); app.use(function(req, res){ res.status(201).end('Created'); }); request(app) .get('/') .expect('Created') .expect(201, done); }) }) }) 4.1.1~dfsg/test/app.router.js 0000644 0000000 0000000 00000032060 12327313561 014677 0 ustar root root var express = require('../') , request = require('supertest') , assert = require('assert') , methods = require('methods'); describe('app.router', function(){ describe('methods supported', function(){ methods.forEach(function(method){ if (method === 'connect') return; it('should include ' + method.toUpperCase(), function(done){ if (method == 'delete') method = 'del'; var app = express(); var calls = []; app[method]('/foo', function(req, res){ if ('head' == method) { res.end(); } else { res.end(method); } }); request(app) [method]('/foo') .expect('head' == method ? '' : method, done); }) }); }) describe('decode querystring', function(){ it('should decode correct params', function(done){ var app = express(); app.get('/:name', function(req, res, next){ res.send(req.params.name); }); request(app) .get('/foo%2Fbar') .expect('foo/bar', done); }) it('should not accept params in malformed paths', function(done) { var app = express(); app.get('/:name', function(req, res, next){ res.send(req.params.name); }); request(app) .get('/%foobar') .expect(400, done); }) it('should not decode spaces', function(done) { var app = express(); app.get('/:name', function(req, res, next){ res.send(req.params.name); }); request(app) .get('/foo+bar') .expect('foo+bar', done); }) it('should work with unicode', function(done) { var app = express(); app.get('/:name', function(req, res, next){ res.send(req.params.name); }); request(app) .get('/%ce%b1') .expect('\u03b1', done); }) }) it('should be .use()able', function(done){ var app = express(); var calls = []; app.use(function(req, res, next){ calls.push('before'); next(); }); app.get('/', function(req, res, next){ calls.push('GET /') next(); }); app.use(function(req, res, next){ calls.push('after'); res.end(); }); request(app) .get('/') .end(function(res){ calls.should.eql(['before', 'GET /', 'after']) done(); }) }) describe('when given a regexp', function(){ it('should match the pathname only', function(done){ var app = express(); app.get(/^\/user\/[0-9]+$/, function(req, res){ res.end('user'); }); request(app) .get('/user/12?foo=bar') .expect('user', done); }) it('should populate req.params with the captures', function(done){ var app = express(); app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function(req, res){ var id = req.params[0] , op = req.params[1]; res.end(op + 'ing user ' + id); }); request(app) .get('/user/10/edit') .expect('editing user 10', done); }) }) describe('case sensitivity', function(){ it('should be disabled by default', function(done){ var app = express(); app.get('/user', function(req, res){ res.end('tj'); }); request(app) .get('/USER') .expect('tj', done); }) describe('when "case sensitive routing" is enabled', function(){ it('should match identical casing', function(done){ var app = express(); app.enable('case sensitive routing'); app.get('/uSer', function(req, res){ res.end('tj'); }); request(app) .get('/uSer') .expect('tj', done); }) it('should not match otherwise', function(done){ var app = express(); app.enable('case sensitive routing'); app.get('/uSer', function(req, res){ res.end('tj'); }); request(app) .get('/user') .expect(404, done); }) }) }) describe('trailing slashes', function(){ it('should be optional by default', function(done){ var app = express(); app.get('/user', function(req, res){ res.end('tj'); }); request(app) .get('/user/') .expect('tj', done); }) describe('when "strict routing" is enabled', function(){ it('should match trailing slashes', function(done){ var app = express(); app.enable('strict routing'); app.get('/user/', function(req, res){ res.end('tj'); }); request(app) .get('/user/') .expect('tj', done); }) it('should match no slashes', function(done){ var app = express(); app.enable('strict routing'); app.get('/user', function(req, res){ res.end('tj'); }); request(app) .get('/user') .expect('tj', done); }) it('should fail when omitting the trailing slash', function(done){ var app = express(); app.enable('strict routing'); app.get('/user/', function(req, res){ res.end('tj'); }); request(app) .get('/user') .expect(404, done); }) it('should fail when adding the trailing slash', function(done){ var app = express(); app.enable('strict routing'); app.get('/user', function(req, res){ res.end('tj'); }); request(app) .get('/user/') .expect(404, done); }) }) }) it('should allow escaped regexp', function(done){ var app = express(); app.get('/user/\\d+', function(req, res){ res.end('woot'); }); request(app) .get('/user/10') .end(function(err, res){ res.statusCode.should.equal(200); request(app) .get('/user/tj') .expect(404, done); }); }) it('should allow literal "."', function(done){ var app = express(); app.get('/api/users/:from..:to', function(req, res){ var from = req.params.from , to = req.params.to; res.end('users from ' + from + ' to ' + to); }); request(app) .get('/api/users/1..50') .expect('users from 1 to 50', done); }) describe('*', function(){ it('should denote a greedy capture group', function(done){ var app = express(); app.get('/user/*.json', function(req, res){ res.end(req.params[0]); }); request(app) .get('/user/tj.json') .expect('tj', done); }) it('should work with several', function(done){ var app = express(); app.get('/api/*.*', function(req, res){ var resource = req.params[0] , format = req.params[1]; res.end(resource + ' as ' + format); }); request(app) .get('/api/users/foo.bar.json') .expect('users/foo.bar as json', done); }) it('should work cross-segment', function(done){ var app = express(); app.get('/api*', function(req, res){ res.send(req.params[0]); }); request(app) .get('/api') .expect('', function(){ request(app) .get('/api/hey') .expect('/hey', done); }); }) it('should allow naming', function(done){ var app = express(); app.get('/api/:resource(*)', function(req, res){ var resource = req.params.resource; res.end(resource); }); request(app) .get('/api/users/0.json') .expect('users/0.json', done); }) it('should not be greedy immediately after param', function(done){ var app = express(); app.get('/user/:user*', function(req, res){ res.end(req.params.user); }); request(app) .get('/user/122') .expect('122', done); }) it('should eat everything after /', function(done){ var app = express(); app.get('/user/:user*', function(req, res){ res.end(req.params.user); }); request(app) .get('/user/122/aaa') .expect('122', done); }) it('should span multiple segments', function(done){ var app = express(); app.get('/file/*', function(req, res){ res.end(req.params[0]); }); request(app) .get('/file/javascripts/jquery.js') .expect('javascripts/jquery.js', done); }) it('should be optional', function(done){ var app = express(); app.get('/file/*', function(req, res){ res.end(req.params[0]); }); request(app) .get('/file/') .expect('', done); }) it('should require a preceeding /', function(done){ var app = express(); app.get('/file/*', function(req, res){ res.end(req.params[0]); }); request(app) .get('/file') .expect(404, done); }) }) describe(':name', function(){ it('should denote a capture group', function(done){ var app = express(); app.get('/user/:user', function(req, res){ res.end(req.params.user); }); request(app) .get('/user/tj') .expect('tj', done); }) it('should match a single segment only', function(done){ var app = express(); app.get('/user/:user', function(req, res){ res.end(req.params.user); }); request(app) .get('/user/tj/edit') .expect(404, done); }) it('should allow several capture groups', function(done){ var app = express(); app.get('/user/:user/:op', function(req, res){ res.end(req.params.op + 'ing ' + req.params.user); }); request(app) .get('/user/tj/edit') .expect('editing tj', done); }) }) describe(':name?', function(){ it('should denote an optional capture group', function(done){ var app = express(); app.get('/user/:user/:op?', function(req, res){ var op = req.params.op || 'view'; res.end(op + 'ing ' + req.params.user); }); request(app) .get('/user/tj') .expect('viewing tj', done); }) it('should populate the capture group', function(done){ var app = express(); app.get('/user/:user/:op?', function(req, res){ var op = req.params.op || 'view'; res.end(op + 'ing ' + req.params.user); }); request(app) .get('/user/tj/edit') .expect('editing tj', done); }) }) describe('.:name', function(){ it('should denote a format', function(done){ var app = express(); app.get('/:name.:format', function(req, res){ res.end(req.params.name + ' as ' + req.params.format); }); request(app) .get('/foo.json') .expect('foo as json', function(){ request(app) .get('/foo') .expect(404, done); }); }) }) describe('.:name?', function(){ it('should denote an optional format', function(done){ var app = express(); app.get('/:name.:format?', function(req, res){ res.end(req.params.name + ' as ' + (req.params.format || 'html')); }); request(app) .get('/foo') .expect('foo as html', function(){ request(app) .get('/foo.json') .expect('foo as json', done); }); }) }) describe('when next() is called', function(){ it('should continue lookup', function(done){ var app = express() , calls = []; app.get('/foo/:bar?', function(req, res, next){ calls.push('/foo/:bar?'); next(); }); app.get('/bar', function(req, res){ assert(0); }); app.get('/foo', function(req, res, next){ calls.push('/foo'); next(); }); app.get('/foo', function(req, res, next){ calls.push('/foo 2'); res.end('done'); }); request(app) .get('/foo') .expect('done', function(){ calls.should.eql(['/foo/:bar?', '/foo', '/foo 2']); done(); }) }) }) describe('when next(err) is called', function(){ it('should break out of app.router', function(done){ var app = express() , calls = []; app.get('/foo/:bar?', function(req, res, next){ calls.push('/foo/:bar?'); next(); }); app.get('/bar', function(req, res){ assert(0); }); app.get('/foo', function(req, res, next){ calls.push('/foo'); next(new Error('fail')); }); app.get('/foo', function(req, res, next){ assert(0); }); app.use(function(err, req, res, next){ res.end(err.message); }) request(app) .get('/foo') .expect('fail', function(){ calls.should.eql(['/foo/:bar?', '/foo']); done(); }) }) }) it('should allow rewriting of the url', function(done){ var app = express(); app.get('/account/edit', function(req, res, next){ req.user = { id: 12 }; // faux authenticated user req.url = '/user/' + req.user.id + '/edit'; next(); }); app.get('/user/:id/edit', function(req, res){ res.send('editing user ' + req.params.id); }); request(app) .get('/account/edit') .expect('editing user 12', done); }) it('should be chainable', function(){ var app = express(); app.get('/', function(){}).should.equal(app); }) }) 4.1.1~dfsg/test/app.routes.error.js 0000644 0000000 0000000 00000002075 12327313561 016033 0 ustar root root var express = require('../') , request = require('supertest'); describe('app', function(){ describe('.VERB()', function(){ it('should only call an error handling routing callback when an error is propagated', function(done){ var app = express(); var a = false; var b = false; var c = false; var d = false; app.get('/', function(req, res, next){ next(new Error('fabricated error')); }, function(req, res, next) { a = true; next(); }, function(err, req, res, next){ b = true; err.message.should.equal('fabricated error'); next(err); }, function(err, req, res, next){ c = true; err.message.should.equal('fabricated error'); next(); }, function(err, req, res, next){ d = true; next(); }, function(req, res){ a.should.be.false; b.should.be.true; c.should.be.true; d.should.be.false; res.send(204); }); request(app) .get('/') .expect(204, done); }) }) }) 4.1.1~dfsg/test/req.acceptsCharset.js 0000644 0000000 0000000 00000002317 12327313561 016324 0 ustar root root var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.acceptsCharset(type)', function(){ describe('when Accept-Charset is not present', function(){ it('should return true', function(done){ var app = express(); app.use(function(req, res, next){ res.end(req.acceptsCharsets('utf-8') ? 'yes' : 'no'); }); request(app) .get('/') .expect('yes', done); }) }) describe('when Accept-Charset is not present', function(){ it('should return true when present', function(done){ var app = express(); app.use(function(req, res, next){ res.end(req.acceptsCharsets('utf-8') ? 'yes' : 'no'); }); request(app) .get('/') .set('Accept-Charset', 'foo, bar, utf-8') .expect('yes', done); }) it('should return false otherwise', function(done){ var app = express(); app.use(function(req, res, next){ res.end(req.acceptsCharsets('utf-8') ? 'yes' : 'no'); }); request(app) .get('/') .set('Accept-Charset', 'foo, bar') .expect('no', done); }) }) }) }) 4.1.1~dfsg/test/res.links.js 0000644 0000000 0000000 00000002102 12327313561 014502 0 ustar root root var express = require('../') , res = express.response; describe('res', function(){ beforeEach(function() { res.removeHeader('link'); }); describe('.links(obj)', function(){ it('should set Link header field', function(){ res.links({ next: 'http://api.example.com/users?page=2', last: 'http://api.example.com/users?page=5' }); res.get('link') .should.equal( 'Moved Temporarily. Redirecting to http://google.com
'); done(); }) }) it('should escape the url', function(done){ var app = express(); app.use(function(req, res){ res.redirect('Moved Temporarily. Redirecting to <lame>
'); done(); }) }) }) describe('when accepting text', function(){ it('should respond with text', function(done){ var app = express(); app.use(function(req, res){ res.redirect('http://google.com'); }); request(app) .get('/') .set('Accept', 'text/plain, */*') .end(function(err, res){ res.headers.should.have.property('location', 'http://google.com'); res.headers.should.have.property('content-length', '51'); res.text.should.equal('Moved Temporarily. Redirecting to http://google.com'); done(); }) }) it('should encode the url', function(done){ var app = express(); app.use(function(req, res){ res.redirect('http://example.com/?param='); }); request(app) .get('/') .set('Host', 'http://example.com') .set('Accept', 'text/plain, */*') .end(function(err, res){ res.text.should.equal('Moved Temporarily. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E'); done(); }) }) }) describe('when accepting neither text or html', function(){ it('should respond with an empty body', function(done){ var app = express(); app.use(function(req, res){ res.redirect('http://google.com'); }); request(app) .get('/') .set('Accept', 'application/octet-stream') .end(function(err, res){ res.should.have.status(302); res.headers.should.have.property('location', 'http://google.com'); res.headers.should.not.have.property('content-type'); res.headers.should.have.property('content-length', '0'); res.text.should.equal(''); done(); }) }) }) }) 4.1.1~dfsg/test/res.json.js 0000644 0000000 0000000 00000010627 12327313561 014346 0 ustar root root var express = require('../') , request = require('supertest') , assert = require('assert'); describe('res', function(){ describe('.json(object)', function(){ it('should not support jsonp callbacks', function(done){ var app = express(); app.use(function(req, res){ res.json({ foo: 'bar' }); }); request(app) .get('/?callback=foo') .expect('{"foo":"bar"}', done); }) describe('when given primitives', function(){ it('should respond with json', function(done){ var app = express(); app.use(function(req, res){ res.json(null); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('null'); done(); }) }) }) describe('when given an array', function(){ it('should respond with json', function(done){ var app = express(); app.use(function(req, res){ res.json(['foo', 'bar', 'baz']); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('["foo","bar","baz"]'); done(); }) }) }) describe('when given an object', function(){ it('should respond with json', function(done){ var app = express(); app.use(function(req, res){ res.json({ name: 'tobi' }); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('{"name":"tobi"}'); done(); }) }) }) describe('"json replacer" setting', function(){ it('should be passed to JSON.stringify()', function(done){ var app = express(); app.set('json replacer', function(key, val){ return '_' == key[0] ? undefined : val; }); app.use(function(req, res){ res.json({ name: 'tobi', _id: 12345 }); }); request(app) .get('/') .end(function(err, res){ res.text.should.equal('{"name":"tobi"}'); done(); }); }) }) describe('"json spaces" setting', function(){ it('should be undefined by default', function(){ var app = express(); assert(undefined === app.get('json spaces')); }) it('should be passed to JSON.stringify()', function(done){ var app = express(); app.set('json spaces', 2); app.use(function(req, res){ res.json({ name: 'tobi', age: 2 }); }); request(app) .get('/') .end(function(err, res){ res.text.should.equal('{\n "name": "tobi",\n "age": 2\n}'); done(); }); }) }) }) describe('.json(status, object)', function(){ it('should respond with json and set the .statusCode', function(done){ var app = express(); app.use(function(req, res){ res.json(201, { id: 1 }); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(201); res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('{"id":1}'); done(); }) }) }) describe('.json(object, status)', function(){ it('should respond with json and set the .statusCode for backwards compat', function(done){ var app = express(); app.use(function(req, res){ res.json({ id: 1 }, 201); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(201); res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('{"id":1}'); done(); }) }) }) it('should not override previous Content-Types', function(done){ var app = express(); app.get('/', function(req, res){ res.type('application/vnd.example+json'); res.json({ hello: 'world' }); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(200); res.headers.should.have.property('content-type', 'application/vnd.example+json'); res.text.should.equal('{"hello":"world"}'); done(); }) }) }) 4.1.1~dfsg/test/app.engine.js 0000644 0000000 0000000 00000004077 12327313561 014633 0 ustar root root var express = require('../') , fs = require('fs'); function render(path, options, fn) { fs.readFile(path, 'utf8', function(err, str){ if (err) return fn(err); str = str.replace('{{user.name}}', options.user.name); fn(null, str); }); } describe('app', function(){ describe('.engine(ext, fn)', function(){ it('should map a template engine', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.engine('.html', render); app.locals.user = { name: 'tobi' }; app.render('user.html', function(err, str){ if (err) return done(err); str.should.equal('tobi
'); done(); }) }) it('should throw when the callback is missing', function(){ var app = express(); (function(){ app.engine('.html', null); }).should.throw('callback function required'); }) it('should work without leading "."', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.engine('html', render); app.locals.user = { name: 'tobi' }; app.render('user.html', function(err, str){ if (err) return done(err); str.should.equal('tobi
'); done(); }) }) it('should work "view engine" setting', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.engine('html', render); app.set('view engine', 'html'); app.locals.user = { name: 'tobi' }; app.render('user', function(err, str){ if (err) return done(err); str.should.equal('tobi
'); done(); }) }) it('should work "view engine" with leading "."', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.engine('.html', render); app.set('view engine', '.html'); app.locals.user = { name: 'tobi' }; app.render('user', function(err, str){ if (err) return done(err); str.should.equal('tobi
'); done(); }) }) }) }) 4.1.1~dfsg/test/res.cookie.js 0000644 0000000 0000000 00000010550 12327313561 014641 0 ustar root root var express = require('../') , request = require('supertest') , mixin = require('utils-merge') , cookie = require('cookie') , cookieParser = require('cookie-parser') describe('res', function(){ describe('.cookie(name, object)', function(){ it('should generate a JSON cookie', function(done){ var app = express(); app.use(function(req, res){ res.cookie('user', { name: 'tobi' }).end(); }); request(app) .get('/') .end(function(err, res){ var val = ['user=' + encodeURIComponent('j:{"name":"tobi"}') + '; Path=/']; res.headers['set-cookie'].should.eql(val); done(); }) }) }) describe('.cookie(name, string)', function(){ it('should set a cookie', function(done){ var app = express(); app.use(function(req, res){ res.cookie('name', 'tobi').end(); }); request(app) .get('/') .end(function(err, res){ var val = ['name=tobi; Path=/']; res.headers['set-cookie'].should.eql(val); done(); }) }) it('should allow multiple calls', function(done){ var app = express(); app.use(function(req, res){ res.cookie('name', 'tobi'); res.cookie('age', 1); res.cookie('gender', '?'); res.end(); }); request(app) .get('/') .end(function(err, res){ var val = ['name=tobi; Path=/', 'age=1; Path=/', 'gender=%3F; Path=/']; res.headers['set-cookie'].should.eql(val); done(); }) }) }) describe('.cookie(name, string, options)', function(){ it('should set params', function(done){ var app = express(); app.use(function(req, res){ res.cookie('name', 'tobi', { httpOnly: true, secure: true }); res.end(); }); request(app) .get('/') .end(function(err, res){ var val = ['name=tobi; Path=/; HttpOnly; Secure']; res.headers['set-cookie'].should.eql(val); done(); }) }) describe('maxAge', function(){ it('should set relative expires', function(done){ var app = express(); app.use(function(req, res){ res.cookie('name', 'tobi', { maxAge: 1000 }); res.end(); }); request(app) .get('/') .end(function(err, res){ res.headers['set-cookie'][0].should.not.include('Thu, 01 Jan 1970 00:00:01 GMT'); done(); }) }) it('should set max-age', function(done){ var app = express(); app.use(function(req, res){ res.cookie('name', 'tobi', { maxAge: 1000 }); res.end(); }); request(app) .get('/') .end(function(err, res){ res.headers['set-cookie'][0].should.include('Max-Age=1'); done(); }) }) it('should not mutate the options object', function(done){ var app = express(); var options = { maxAge: 1000 }; var optionsCopy = mixin({}, options); app.use(function(req, res){ res.cookie('name', 'tobi', options) res.end(); }); request(app) .get('/') .end(function(err, res){ options.should.eql(optionsCopy); done(); }) }) }) describe('signed', function(){ it('should generate a signed JSON cookie', function(done){ var app = express(); app.use(cookieParser('foo bar baz')); app.use(function(req, res){ res.cookie('user', { name: 'tobi' }, { signed: true }).end(); }); request(app) .get('/') .end(function(err, res){ var val = res.headers['set-cookie'][0]; val = cookie.parse(val.split('.')[0]); val.user.should.equal('s:j:{"name":"tobi"}'); done(); }) }) }) describe('.signedCookie(name, string)', function(){ it('should set a signed cookie', function(done){ var app = express(); app.use(cookieParser('foo bar baz')); app.use(function(req, res){ res.cookie('name', 'tobi', { signed: true }).end(); }); request(app) .get('/') .end(function(err, res){ var val = ['name=s%3Atobi.xJjV2iZ6EI7C8E5kzwbfA9PVLl1ZR07UTnuTgQQ4EnQ; Path=/']; res.headers['set-cookie'].should.eql(val); done(); }) }) }) }) }) 4.1.1~dfsg/test/utils.js 0000644 0000000 0000000 00000002200 12327313561 013731 0 ustar root root var utils = require('../lib/utils') , assert = require('assert'); describe('utils.etag(body)', function(){ var str = 'Hello CRC'; var strUTF8 = '\n\n\n\n自動販売
'; it('should support strings', function(){ utils.etag(str).should.eql('"-2034458343"'); }) it('should support utf8 strings', function(){ utils.etag(strUTF8).should.eql('"1395090196"'); }) it('should support buffer', function(){ utils.etag(new Buffer(strUTF8)).should.eql('"1395090196"'); utils.etag(new Buffer(str)).should.eql('"-2034458343"'); }) }) describe('utils.isAbsolute()', function(){ it('should support windows', function(){ assert(utils.isAbsolute('c:\\')); assert(!utils.isAbsolute(':\\')); }) it('should unices', function(){ assert(utils.isAbsolute('/foo/bar')); assert(!utils.isAbsolute('foo/bar')); }) }) describe('utils.flatten(arr)', function(){ it('should flatten an array', function(){ var arr = ['one', ['two', ['three', 'four'], 'five']]; utils.flatten(arr) .should.eql(['one', 'two', 'three', 'four', 'five']); }) }) 4.1.1~dfsg/test/app.route.js 0000644 0000000 0000000 00000001734 12327313561 014521 0 ustar root root var express = require('../'); var request = require('supertest'); describe('app.route', function(){ it('should return a new route', function(done){ var app = express(); app.route('/foo') .get(function(req, res) { res.send('get'); }) .post(function(req, res) { res.send('post'); }); request(app) .post('/foo') .expect('post', done); }); it('should all .VERB after .all', function(done){ var app = express(); app.route('/foo') .all(function(req, res, next) { next(); }) .get(function(req, res) { res.send('get'); }) .post(function(req, res) { res.send('post'); }); request(app) .post('/foo') .expect('post', done); }); it('should support dynamic routes', function(done){ var app = express(); app.route('/:foo') .get(function(req, res) { res.send(req.params.foo); }); request(app) .get('/test') .expect('test', done); }); }); 4.1.1~dfsg/test/res.format.js 0000644 0000000 0000000 00000006422 12327313561 014663 0 ustar root root var express = require('../') , request = require('supertest') , utils = require('../lib/utils') , assert = require('assert'); var app = express(); app.use(function(req, res, next){ res.format({ 'text/plain': function(){ res.send('hey'); }, 'text/html': function(){ res.send('hey
'); }, 'application/json': function(a, b, c){ assert(req == a); assert(res == b); assert(next == c); res.send({ message: 'hey' }); } }); }); app.use(function(err, req, res, next){ if (!err.types) throw err; res.send(err.status, 'Supports: ' + err.types.join(', ')); }) var app2 = express(); app2.use(function(req, res, next){ res.format({ text: function(){ res.send('hey') }, html: function(){ res.send('hey
') }, json: function(){ res.send({ message: 'hey' }) } }); }); app2.use(function(err, req, res, next){ res.send(err.status, 'Supports: ' + err.types.join(', ')); }) var app3 = express(); app3.use(function(req, res, next){ res.format({ text: function(){ res.send('hey') }, default: function(){ res.send('default') } }) }); describe('res', function(){ describe('.format(obj)', function(){ describe('with canonicalized mime types', function(){ test(app); }) describe('with extnames', function(){ test(app2); }) describe('given .default', function(){ it('should be invoked instead of auto-responding', function(done){ request(app3) .get('/') .set('Accept: text/html') .expect('default', done); }) }) }) }) function test(app) { it('should utilize qvalues in negotiation', function(done){ request(app) .get('/') .set('Accept', 'text/html; q=.5, application/json, */*; q=.1') .expect({"message":"hey"}, done); }) it('should allow wildcard type/subtypes', function(done){ request(app) .get('/') .set('Accept', 'text/html; q=.5, application/*, */*; q=.1') .expect({"message":"hey"}, done); }) it('should default the Content-Type', function(done){ request(app) .get('/') .set('Accept', 'text/html; q=.5, text/plain') .expect('Content-Type', 'text/plain; charset=utf-8') .expect('hey', done); }) it('should set the correct charset for the Content-Type', function() { request(app) .get('/') .set('Accept', 'text/html') .expect('Content-Type', 'text/html; charset=utf-8'); request(app) .get('/') .set('Accept', 'text/plain') .expect('Content-Type', 'text/plain; charset=utf-8'); request(app) .get('/') .set('Accept', 'application/json') .expect('Content-Type', 'application/json'); }) it('should Vary: Accept', function(done){ request(app) .get('/') .set('Accept', 'text/html; q=.5, text/plain') .expect('Vary', 'Accept', done); }) describe('when Accept is not present', function(){ it('should invoke the first callback', function(done){ request(app) .get('/') .expect('hey', done); }) }) describe('when no match is made', function(){ it('should should respond with 406 not acceptable', function(done){ request(app) .get('/') .set('Accept', 'foo/bar') .expect('Supports: text/plain, text/html, application/json') .expect(406, done) }) }) } 4.1.1~dfsg/test/res.jsonp.js 0000644 0000000 0000000 00000015003 12327313561 014517 0 ustar root root var express = require('../') , request = require('supertest') , assert = require('assert'); describe('res', function(){ describe('.jsonp(object)', function(){ it('should respond with jsonp', function(done){ var app = express(); app.use(function(req, res){ res.jsonp({ count: 1 }); }); request(app) .get('/?callback=something') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8'); res.text.should.equal('typeof something === \'function\' && something({"count":1});'); done(); }) }) it('should use first callback parameter with jsonp', function(done){ var app = express(); app.use(function(req, res){ res.jsonp({ count: 1 }); }); request(app) .get('/?callback=something&callback=somethingelse') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8'); res.text.should.equal('typeof something === \'function\' && something({"count":1});'); done(); }) }) it('should allow renaming callback', function(done){ var app = express(); app.set('jsonp callback name', 'clb'); app.use(function(req, res){ res.jsonp({ count: 1 }); }); request(app) .get('/?clb=something') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8'); res.text.should.equal('typeof something === \'function\' && something({"count":1});'); done(); }) }) it('should allow []', function(done){ var app = express(); app.use(function(req, res){ res.jsonp({ count: 1 }); }); request(app) .get('/?callback=callbacks[123]') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8'); res.text.should.equal('typeof callbacks[123] === \'function\' && callbacks[123]({"count":1});'); done(); }) }) it('should disallow arbitrary js', function(done){ var app = express(); app.use(function(req, res){ res.jsonp({}); }); request(app) .get('/?callback=foo;bar()') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8'); res.text.should.equal('typeof foobar === \'function\' && foobar({});'); done(); }) }) it('should escape utf whitespace', function(done){ var app = express(); app.use(function(req, res){ res.jsonp({ str: '\u2028 \u2029 woot' }); }); request(app) .get('/?callback=foo') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/javascript; charset=utf-8'); res.text.should.equal('typeof foo === \'function\' && foo({"str":"\\u2028 \\u2029 woot"});'); done(); }); }); describe('when given primitives', function(){ it('should respond with json', function(done){ var app = express(); app.use(function(req, res){ res.jsonp(null); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('null'); done(); }) }) }) describe('when given an array', function(){ it('should respond with json', function(done){ var app = express(); app.use(function(req, res){ res.jsonp(['foo', 'bar', 'baz']); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('["foo","bar","baz"]'); done(); }) }) }) describe('when given an object', function(){ it('should respond with json', function(done){ var app = express(); app.use(function(req, res){ res.jsonp({ name: 'tobi' }); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('{"name":"tobi"}'); done(); }) }) }) describe('"json replacer" setting', function(){ it('should be passed to JSON.stringify()', function(done){ var app = express(); app.set('json replacer', function(key, val){ return '_' == key[0] ? undefined : val; }); app.use(function(req, res){ res.jsonp({ name: 'tobi', _id: 12345 }); }); request(app) .get('/') .end(function(err, res){ res.text.should.equal('{"name":"tobi"}'); done(); }); }) }) describe('"json spaces" setting', function(){ it('should be undefined by default', function(){ var app = express(); assert(undefined === app.get('json spaces')); }) it('should be passed to JSON.stringify()', function(done){ var app = express(); app.set('json spaces', 2); app.use(function(req, res){ res.jsonp({ name: 'tobi', age: 2 }); }); request(app) .get('/') .end(function(err, res){ res.text.should.equal('{\n "name": "tobi",\n "age": 2\n}'); done(); }); }) }) }) describe('.json(status, object)', function(){ it('should respond with json and set the .statusCode', function(done){ var app = express(); app.use(function(req, res){ res.jsonp(201, { id: 1 }); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(201); res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('{"id":1}'); done(); }) }) }) describe('.json(object, status)', function(){ it('should respond with json and set the .statusCode for backwards compat', function(done){ var app = express(); app.use(function(req, res){ res.jsonp({ id: 1 }, 201); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(201); res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('{"id":1}'); done(); }) }) }) }) 4.1.1~dfsg/test/app.js 0000644 0000000 0000000 00000003706 12327313561 013365 0 ustar root root var express = require('../') , assert = require('assert'); describe('app', function(){ it('should inherit from event emitter', function(done){ var app = express(); app.on('foo', done); app.emit('foo'); }) }) describe('app.parent', function(){ it('should return the parent when mounted', function(){ var app = express() , blog = express() , blogAdmin = express(); app.use('/blog', blog); blog.use('/admin', blogAdmin); assert(!app.parent, 'app.parent'); blog.parent.should.equal(app); blogAdmin.parent.should.equal(blog); }) }) describe('app.mountpath', function(){ it('should return the mounted path', function(){ var app = express() , blog = express() , blogAdmin = express(); app.use('/blog', blog); blog.use('/admin', blogAdmin); app.mountpath.should.equal('/'); blog.mountpath.should.equal('/blog'); blogAdmin.mountpath.should.equal('/admin'); }) }) describe('app.router', function(){ it('should throw with notice', function(done){ var app = express() try { app.router; } catch(err) { done(); } }) }) describe('app.path()', function(){ it('should return the canonical', function(){ var app = express() , blog = express() , blogAdmin = express(); app.use('/blog', blog); blog.use('/admin', blogAdmin); app.path().should.equal(''); blog.path().should.equal('/blog'); blogAdmin.path().should.equal('/blog/admin'); }) }) describe('in development', function(){ it('should disable "view cache"', function(){ process.env.NODE_ENV = 'development'; var app = express(); app.enabled('view cache').should.be.false; process.env.NODE_ENV = 'test'; }) }) describe('in production', function(){ it('should enable "view cache"', function(){ process.env.NODE_ENV = 'production'; var app = express(); app.enabled('view cache').should.be.true; process.env.NODE_ENV = 'test'; }) }) 4.1.1~dfsg/test/res.attachment.js 0000644 0000000 0000000 00000003576 12327313561 015532 0 ustar root root var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.attachment()', function(){ it('should Content-Disposition to attachment', function(done){ var app = express(); app.use(function(req, res){ res.attachment().send('foo'); }); request(app) .get('/') .expect('Content-Disposition', 'attachment', done); }) }) describe('.attachment(filename)', function(){ it('should add the filename param', function(done){ var app = express(); app.use(function(req, res){ res.attachment('/path/to/image.png'); res.send('foo'); }); request(app) .get('/') .expect('Content-Disposition', 'attachment; filename="image.png"', done); }) it('should set the Content-Type', function(done){ var app = express(); app.use(function(req, res){ res.attachment('/path/to/image.png'); res.send('foo'); }); request(app) .get('/') .expect('Content-Type', 'image/png', done); }) }) describe('.attachment(utf8filename)', function(){ it('should add the filename and filename* params', function(done){ var app = express(); app.use(function(req, res){ res.attachment('/locales/日本語.txt'); res.send('japanese'); }); request(app) .get('/') .expect('Content-Disposition', 'attachment;' + ' filename=%E6%97%A5%E6%9C%AC%E8%AA%9E.txt;' + ' filename*=UTF-8\'\'%E6%97%A5%E6%9C%AC%E8%AA%9E.txt', done); }) it('should set the Content-Type', function(done){ var app = express(); app.use(function(req, res){ res.attachment('/locales/日本語.txt'); res.send('japanese'); }); request(app) .get('/') .expect('Content-Type', 'text/plain; charset=utf-8', done); }) }) }) 4.1.1~dfsg/test/app.locals.js 0000644 0000000 0000000 00000001442 12327313561 014634 0 ustar root root var express = require('../') , request = require('supertest'); describe('app', function(){ describe('.locals(obj)', function(){ it('should merge locals', function(){ var app = express(); Object.keys(app.locals).should.eql(['settings']); app.locals.user = 'tobi'; app.locals.age = 2; Object.keys(app.locals).should.eql(['settings', 'user', 'age']); app.locals.user.should.equal('tobi'); app.locals.age.should.equal(2); }) }) describe('.locals.settings', function(){ it('should expose app settings', function(){ var app = express(); app.set('title', 'House of Manny'); var obj = app.locals.settings; obj.should.have.property('env', 'test'); obj.should.have.property('title', 'House of Manny'); }) }) }) 4.1.1~dfsg/test/middleware.basic.js 0000644 0000000 0000000 00000002122 12327313561 015771 0 ustar root root var express = require('../'); var request = require('supertest'); describe('middleware', function(){ describe('.next()', function(){ it('should behave like connect', function(done){ var app = express() , calls = []; app.use(function(req, res, next){ calls.push('one'); next(); }); app.use(function(req, res, next){ calls.push('two'); next(); }); app.use(function(req, res){ var buf = ''; res.setHeader('Content-Type', 'application/json'); req.setEncoding('utf8'); req.on('data', function(chunk){ buf += chunk }); req.on('end', function(){ res.end(buf); }); }); request(app.listen()) .get('/') .set('Content-Type', 'application/json') .send('{"foo":"bar"}') .end(function(err, res){ if (err) return done(err); res.headers.should.have.property('content-type', 'application/json'); res.statusCode.should.equal(200); res.text.should.equal('{"foo":"bar"}'); done(); }) }) }) }) 4.1.1~dfsg/test/app.del.js 0000644 0000000 0000000 00000000522 12327313561 014121 0 ustar root root var express = require('../') , request = require('supertest'); describe('app.del()', function(){ it('should alias app.delete()', function(done){ var app = express(); app.del('/tobi', function(req, res){ res.end('deleted tobi!'); }); request(app) .del('/tobi') .expect('deleted tobi!', done); }) }) 4.1.1~dfsg/test/req.ip.js 0000644 0000000 0000000 00000002562 12327313561 014002 0 ustar root root var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.ip', function(){ describe('when X-Forwarded-For is present', function(){ describe('when "trust proxy" is enabled', function(){ it('should return the client addr', function(done){ var app = express(); app.enable('trust proxy'); app.use(function(req, res, next){ res.send(req.ip); }); request(app) .get('/') .set('X-Forwarded-For', 'client, p1, p2') .expect('client', done); }) }) describe('when "trust proxy" is disabled', function(){ it('should return the remote address', function(done){ var app = express(); app.use(function(req, res, next){ res.send(req.ip); }); request(app) .get('/') .set('X-Forwarded-For', 'client, p1, p2') .expect('127.0.0.1', done); }) }) }) describe('when X-Forwarded-For is not present', function(){ it('should return the remote address', function(done){ var app = express(); app.enable('trust proxy'); app.use(function(req, res, next){ res.send(req.ip); }); request(app) .get('/') .expect('127.0.0.1', done); }) }) }) }) 4.1.1~dfsg/test/res.set.js 0000644 0000000 0000000 00000003735 12327313561 014172 0 ustar root root var express = require('../') , request = require('supertest') , res = express.response; describe('res', function(){ describe('.set(field, value)', function(){ it('should set the response header field', function(done){ var app = express(); app.use(function(req, res){ res.set('Content-Type', 'text/x-foo; charset=utf-8').end(); }); request(app) .get('/') .expect('Content-Type', 'text/x-foo; charset=utf-8') .end(done); }) it('should coerce to a string', function(){ res.headers = {}; res.set('ETag', 123); res.get('ETag').should.equal('123'); }) }) describe('.set(field, values)', function(){ it('should set multiple response header fields', function(done){ var app = express(); app.use(function(req, res){ res.set('Set-Cookie', ["type=ninja", "language=javascript"]); res.send(res.get('Set-Cookie')); }); request(app) .get('/') .expect('["type=ninja","language=javascript"]', done); }) it('should coerce to an array of strings', function(){ res.headers = {}; res.set('ETag', [123, 456]); JSON.stringify(res.get('ETag')).should.equal('["123","456"]'); }) it('should not set a charset of one is already set', function () { res.headers = {}; res.set('Content-Type', 'text/html; charset=lol'); res.get('content-type').should.equal('text/html; charset=lol'); }) }) describe('.set(object)', function(){ it('should set multiple fields', function(done){ var app = express(); app.use(function(req, res){ res.set({ 'X-Foo': 'bar', 'X-Bar': 'baz' }).end(); }); request(app) .get('/') .expect('X-Foo', 'bar') .expect('X-Bar', 'baz') .end(done); }) it('should coerce to a string', function(){ res.headers = {}; res.set({ ETag: 123 }); res.get('ETag').should.equal('123'); }) }) }) 4.1.1~dfsg/test/req.protocol.js 0000644 0000000 0000000 00000002604 12327313561 015230 0 ustar root root var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.protocol', function(){ it('should return the protocol string', function(done){ var app = express(); app.use(function(req, res){ res.end(req.protocol); }); request(app) .get('/') .expect('http', done); }) describe('when "trust proxy" is enabled', function(){ it('should respect X-Forwarded-Proto', function(done){ var app = express(); app.enable('trust proxy'); app.use(function(req, res){ res.end(req.protocol); }); request(app) .get('/') .set('X-Forwarded-Proto', 'https') .expect('https', done); }) it('should default to http', function(done){ var app = express(); app.enable('trust proxy'); app.use(function(req, res){ res.end(req.protocol); }); request(app) .get('/') .expect('http', done); }) }) describe('when "trust proxy" is disabled', function(){ it('should ignore X-Forwarded-Proto', function(done){ var app = express(); app.use(function(req, res){ res.end(req.protocol); }); request(app) .get('/') .set('X-Forwarded-Proto', 'https') .expect('http', done); }) }) }) }) 4.1.1~dfsg/test/res.location.js 0000644 0000000 0000000 00000000747 12327313561 015207 0 ustar root root var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.location(url)', function(){ it('should set the header', function(done){ var app = express(); app.use(function(req, res){ res.location('http://google.com').end(); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('location', 'http://google.com'); done(); }) }) }) }) 4.1.1~dfsg/test/req.path.js 0000644 0000000 0000000 00000000617 12327313561 014325 0 ustar root root var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.path', function(){ it('should return the parsed pathname', function(done){ var app = express(); app.use(function(req, res){ res.end(req.path); }); request(app) .get('/login?redirect=/post/1/comments') .expect('/login', done); }) }) }) 4.1.1~dfsg/test/Route.js 0000644 0000000 0000000 00000007010 12327313561 013673 0 ustar root root var express = require('../') , Route = express.Route , methods = require('methods') , assert = require('assert'); describe('Route', function(){ describe('.all', function(){ it('should add handler', function(done){ var route = new Route('/foo'); route.all(function(req, res, next) { assert.equal(req.a, 1); assert.equal(res.b, 2); next(); }); route.dispatch({ a:1, method: 'GET' }, { b:2 }, done); }) it('should handle VERBS', function(done) { var route = new Route('/foo'); var count = 0; route.all(function(req, res, next) { count++; }); methods.forEach(function testMethod(method) { route.dispatch({ method: method }, {}); }); assert.equal(count, methods.length); done(); }) it('should stack', function(done) { var route = new Route('/foo'); var count = 0; route.all(function(req, res, next) { count++; next(); }); route.all(function(req, res, next) { count++; next(); }); route.dispatch({ method: 'GET' }, {}, function(err) { assert.ifError(err); count++; }); assert.equal(count, 3); done(); }) }) describe('.VERB', function(){ it('should support .get', function(done){ var route = new Route(''); var count = 0; route.get(function(req, res, next) { count++; }) route.dispatch({ method: 'GET' }, {}); assert(count); done(); }) it('should limit to just .VERB', function(done){ var route = new Route(''); route.get(function(req, res, next) { assert(false); done(); }) route.post(function(req, res, next) { assert(true); }) route.dispatch({ method: 'post' }, {}); done(); }) it('should allow fallthrough', function(done){ var route = new Route(''); var order = ''; route.get(function(req, res, next) { order += 'a'; next(); }) route.all(function(req, res, next) { order += 'b'; next(); }); route.get(function(req, res, next) { order += 'c'; }) route.dispatch({ method: 'get' }, {}); assert.equal(order, 'abc'); done(); }) }) describe('errors', function(){ it('should handle errors via arity 4 functions', function(done){ var route = new Route(''); var order = ''; route.all(function(req, res, next){ next(new Error('foobar')); }); route.all(function(req, res, next){ order += '0'; next(); }); route.all(function(err, req, res, next){ order += 'a'; next(err); }); route.all(function(err, req, res, next){ assert.equal(err.message, 'foobar'); assert.equal(order, 'a'); done(); }); route.dispatch({ method: 'get' }, {}); }) it('should handle throw', function(done) { var route = new Route(''); var order = ''; route.all(function(req, res, next){ throw new Error('foobar'); }); route.all(function(req, res, next){ order += '0'; next(); }); route.all(function(err, req, res, next){ order += 'a'; next(err); }); route.all(function(err, req, res, next){ assert.equal(err.message, 'foobar'); assert.equal(order, 'a'); done(); }); route.dispatch({ method: 'get' }, {}); }); }) }) 4.1.1~dfsg/test/res.locals.js 0000644 0000000 0000000 00000001404 12327313561 014643 0 ustar root root var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.locals', function(){ it('should be empty by default', function(done){ var app = express(); app.use(function(req, res){ Object.keys(res.locals).should.eql([]); res.end(); }); request(app) .get('/') .expect(200, done); }) }) it('should work when mounted', function(done){ var app = express(); var blog = express(); app.use(blog); blog.use(function(req, res, next){ res.locals.foo = 'bar'; next(); }); app.use(function(req, res){ res.locals.foo.should.equal('bar'); res.end(); }); request(app) .get('/') .expect(200, done); }) }) 4.1.1~dfsg/test/res.vary.js 0000644 0000000 0000000 00000002577 12327313561 014363 0 ustar root root var express = require('../') , should = require('should'); function response() { var res = Object.create(express.response); res._headers = {}; return res; } describe('res.vary()', function(){ describe('with no arguments', function(){ it('should not set Vary', function(){ var res = response(); res.vary(); should.not.exist(res.get('Vary')); }) }) describe('with an empty array', function(){ it('should not set Vary', function(){ var res = response(); res.vary([]); should.not.exist(res.get('Vary')); }) }) describe('with an array', function(){ it('should set the values', function(){ var res = response(); res.vary(['Accept', 'Accept-Language', 'Accept-Encoding']); res.get('Vary').should.equal('Accept, Accept-Language, Accept-Encoding'); }) }) describe('with a string', function(){ it('should set the value', function(){ var res = response(); res.vary('Accept'); res.get('Vary').should.equal('Accept'); }) }) describe('when the value is present', function(){ it('should not add it again', function(){ var res = response(); res.vary('Accept'); res.vary('Accept-Encoding'); res.vary('Accept-Encoding'); res.vary('Accept-Encoding'); res.vary('Accept'); res.get('Vary').should.equal('Accept, Accept-Encoding'); }) }) }) 4.1.1~dfsg/test/regression.js 0000644 0000000 0000000 00000000554 12327313561 014763 0 ustar root root var express = require('../') , request = require('supertest'); describe('throw after .end()', function(){ it('should fail gracefully', function(done){ var app = express(); app.get('/', function(req, res){ res.end('yay'); throw new Error('boom'); }); request(app) .get('/') .expect('yay') .expect(200, done); }) }) 4.1.1~dfsg/test/config.js 0000644 0000000 0000000 00000004533 12327313561 014051 0 ustar root root var express = require('../') , assert = require('assert'); describe('config', function(){ describe('.set()', function(){ it('should set a value', function(){ var app = express(); app.set('foo', 'bar').should.equal(app); }) it('should return the app when undefined', function(){ var app = express(); app.set('foo', undefined).should.equal(app); }) }) describe('.get()', function(){ it('should return undefined when unset', function(){ var app = express(); assert(undefined === app.get('foo')); }) it('should otherwise return the value', function(){ var app = express(); app.set('foo', 'bar'); app.get('foo').should.equal('bar'); }) describe('when mounted', function(){ it('should default to the parent app', function(){ var app = express() , blog = express(); app.set('title', 'Express'); app.use(blog); blog.get('title').should.equal('Express'); }) it('should given precedence to the child', function(){ var app = express() , blog = express(); app.use(blog); app.set('title', 'Express'); blog.set('title', 'Some Blog'); blog.get('title').should.equal('Some Blog'); }) }) }) describe('.enable()', function(){ it('should set the value to true', function(){ var app = express(); app.enable('tobi').should.equal(app); app.get('tobi').should.be.true; }) }) describe('.disable()', function(){ it('should set the value to false', function(){ var app = express(); app.disable('tobi').should.equal(app); app.get('tobi').should.be.false; }) }) describe('.enabled()', function(){ it('should default to false', function(){ var app = express(); app.enabled('foo').should.be.false; }) it('should return true when set', function(){ var app = express(); app.set('foo', 'bar'); app.enabled('foo').should.be.true; }) }) describe('.disabled()', function(){ it('should default to true', function(){ var app = express(); app.disabled('foo').should.be.true; }) it('should return false when set', function(){ var app = express(); app.set('foo', 'bar'); app.disabled('foo').should.be.false; }) }) }) 4.1.1~dfsg/test/req.host.js 0000644 0000000 0000000 00000001320 12327313561 014336 0 ustar root root var express = require('../') , request = require('supertest') , assert = require('assert'); describe('req', function(){ describe('.host', function(){ it('should return the Host when present', function(done){ var app = express(); app.use(function(req, res){ res.end(req.host); }); request(app) .post('/') .set('Host', 'example.com') .expect('example.com', done); }) it('should return undefined otherwise', function(done){ var app = express(); app.use(function(req, res){ req.headers.host = null; res.end(String(req.host)); }); request(app) .post('/') .expect('undefined', done); }) }) }) 4.1.1~dfsg/test/exports.js 0000644 0000000 0000000 00000002437 12327313561 014311 0 ustar root root var express = require('../'); var request = require('supertest'); var assert = require('assert'); describe('exports', function(){ it('should expose Router', function(){ express.Router.should.be.a.Function; }) it('should expose the application prototype', function(){ express.application.set.should.be.a.Function; }) it('should expose the request prototype', function(){ express.request.accepts.should.be.a.Function; }) it('should expose the response prototype', function(){ express.response.send.should.be.a.Function; }) it('should permit modifying the .application prototype', function(){ express.application.foo = function(){ return 'bar'; }; express().foo().should.equal('bar'); }) it('should permit modifying the .request prototype', function(done){ express.request.foo = function(){ return 'bar'; }; var app = express(); app.use(function(req, res, next){ res.end(req.foo()); }); request(app) .get('/') .expect('bar', done); }) it('should permit modifying the .response prototype', function(done){ express.response.foo = function(){ this.send('bar'); }; var app = express(); app.use(function(req, res, next){ res.foo(); }); request(app) .get('/') .expect('bar', done); }) }) 4.1.1~dfsg/test/res.send.js 0000644 0000000 0000000 00000022031 12327313561 014316 0 ustar root root var express = require('../') , request = require('supertest') , assert = require('assert'); describe('res', function(){ describe('.send(null)', function(){ it('should set body to ""', function(done){ var app = express(); app.use(function(req, res){ res.send(null); }); request(app) .get('/') .expect('Content-Length', '0') .expect('', done); }) }) describe('.send(undefined)', function(){ it('should set body to ""', function(done){ var app = express(); app.use(function(req, res){ res.send(undefined); }); request(app) .get('/') .expect('', function(req, res){ res.header.should.not.have.property('content-length'); done(); }); }) }) describe('.send(code)', function(){ it('should set .statusCode', function(done){ var app = express(); app.use(function(req, res){ res.send(201).should.equal(res); }); request(app) .get('/') .expect('Created') .expect(201, done); }) }) describe('.send(code, body)', function(){ it('should set .statusCode and body', function(done){ var app = express(); app.use(function(req, res){ res.send(201, 'Created :)'); }); request(app) .get('/') .expect('Created :)') .expect(201, done); }) }) describe('.send(body, code)', function(){ it('should be supported for backwards compat', function(done){ var app = express(); app.use(function(req, res){ res.send('Bad!', 400); }); request(app) .get('/') .expect('Bad!') .expect(400, done); }) }) describe('.send(String)', function(){ it('should send as html', function(done){ var app = express(); app.use(function(req, res){ res.send('hey
'); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/html; charset=utf-8'); res.text.should.equal('hey
'); res.statusCode.should.equal(200); done(); }) }) it('should set ETag', function(done){ var app = express(); app.use(function(req, res){ var str = Array(1024 * 2).join('-'); res.send(str); }); request(app) .get('/') .expect('ETag', '"-1498647312"') .end(done); }) it('should not set ETag for non-GET/HEAD', function(done){ var app = express(); app.use(function(req, res){ var str = Array(1024 * 2).join('-'); res.send(str); }); request(app) .post('/') .end(function(err, res){ if (err) return done(err); assert(!res.header.etag, 'has an ETag'); done(); }); }) it('should not override Content-Type', function(done){ var app = express(); app.use(function(req, res){ res.set('Content-Type', 'text/plain').send('hey'); }); request(app) .get('/') .expect('Content-Type', 'text/plain; charset=utf-8') .expect('hey') .expect(200, done); }) }) describe('.send(Buffer)', function(){ it('should send as octet-stream', function(done){ var app = express(); app.use(function(req, res){ res.send(new Buffer('hello')); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/octet-stream'); res.text.should.equal('hello'); res.statusCode.should.equal(200); done(); }) }) it('should set ETag', function(done){ var app = express(); app.use(function(req, res){ var str = Array(1024 * 2).join('-'); res.send(new Buffer(str)); }); request(app) .get('/') .expect('ETag', '"-1498647312"') .end(done); }) it('should not override Content-Type', function(done){ var app = express(); app.use(function(req, res){ res.set('Content-Type', 'text/plain').send(new Buffer('hey')); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'text/plain; charset=utf-8'); res.text.should.equal('hey'); res.statusCode.should.equal(200); done(); }) }) }) describe('.send(Object)', function(){ it('should send as application/json', function(done){ var app = express(); app.use(function(req, res){ res.send({ name: 'tobi' }); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('content-type', 'application/json'); res.text.should.equal('{"name":"tobi"}'); done(); }) }) }) describe('when the request method is HEAD', function(){ it('should ignore the body', function(done){ var app = express(); app.use(function(req, res){ res.send('yay'); }); request(app) .head('/') .expect('', done); }) }) describe('when .statusCode is 204', function(){ it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){ var app = express(); app.use(function(req, res){ res.status(204).set('Transfer-Encoding', 'chunked').send('foo'); }); request(app) .get('/') .end(function(err, res){ res.headers.should.not.have.property('content-type'); res.headers.should.not.have.property('content-length'); res.headers.should.not.have.property('transfer-encoding'); res.text.should.equal(''); done(); }) }) }) describe('when .statusCode is 304', function(){ it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){ var app = express(); app.use(function(req, res){ res.status(304).set('Transfer-Encoding', 'chunked').send('foo'); }); request(app) .get('/') .end(function(err, res){ res.headers.should.not.have.property('content-type'); res.headers.should.not.have.property('content-length'); res.headers.should.not.have.property('transfer-encoding'); res.text.should.equal(''); done(); }) }) }) it('should always check regardless of length', function(done){ var app = express(); app.use(function(req, res, next){ res.set('ETag', 'asdf'); res.send('hey'); }); request(app) .get('/') .set('If-None-Match', 'asdf') .expect(304, done); }) it('should respond with 304 Not Modified when fresh', function(done){ var app = express(); app.use(function(req, res){ var str = Array(1024 * 2).join('-'); res.send(str); }); request(app) .get('/') .set('If-None-Match', '"-1498647312"') .expect(304, done); }) it('should not perform freshness check unless 2xx or 304', function(done){ var app = express(); app.use(function(req, res, next){ res.status(500); res.set('ETag', 'asdf'); res.send('hey'); }); request(app) .get('/') .set('If-None-Match', 'asdf') .expect('hey') .expect(500, done); }) it('should not support jsonp callbacks', function(done){ var app = express(); app.use(function(req, res){ res.send({ foo: 'bar' }); }); request(app) .get('/?callback=foo') .expect('{"foo":"bar"}', done); }) describe('"etag" setting', function(){ describe('when enabled', function(){ it('should send ETag even when content-length < 1024', function(done){ var app = express(); app.use(function(req, res){ res.send('kajdslfkasdf'); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('etag'); done(); }); }) it('should send ETag ', function(done){ var app = express(); app.use(function(req, res){ var str = Array(1024 * 2).join('-'); res.send(str); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('etag', '"-1498647312"'); done(); }); }); }); describe('when disabled', function(){ it('should send no ETag', function(done){ var app = express(); app.use(function(req, res){ var str = Array(1024 * 2).join('-'); res.send(str); }); app.disable('etag'); request(app) .get('/') .end(function(err, res){ res.headers.should.not.have.property('etag'); done(); }); }); it('should send ETag when manually set', function(done){ var app = express(); app.disable('etag'); app.use(function(req, res){ res.set('etag', 1); res.send(200); }); request(app) .get('/') .end(function(err, res){ res.headers.should.have.property('etag'); done(); }); }); }); }) }) 4.1.1~dfsg/test/app.request.js 0000644 0000000 0000000 00000000771 12327313561 015053 0 ustar root root var express = require('../') , request = require('supertest'); describe('app', function(){ describe('.request', function(){ it('should extend the request prototype', function(done){ var app = express(); app.request.querystring = function(){ return require('url').parse(this.url).query; }; app.use(function(req, res){ res.end(req.querystring()); }); request(app) .get('/foo?name=tobi') .expect('name=tobi', done); }) }) }) 4.1.1~dfsg/test/app.listen.js 0000644 0000000 0000000 00000000556 12327313561 014662 0 ustar root root var express = require('../') , request = require('supertest'); describe('app.listen()', function(){ it('should wrap with an HTTP server', function(done){ var app = express(); app.del('/tobi', function(req, res){ res.end('deleted tobi!'); }); var server = app.listen(9999, function(){ server.close(); done(); }); }) }) 4.1.1~dfsg/test/app.options.js 0000644 0000000 0000000 00000002605 12327313561 015054 0 ustar root root var express = require('../') , request = require('supertest'); describe('OPTIONS', function(){ it('should default to the routes defined', function(done){ var app = express(); app.del('/', function(){}); app.get('/users', function(req, res){}); app.put('/users', function(req, res){}); request(app) .options('/users') .expect('GET,PUT') .expect('Allow', 'GET,PUT', done); }) it('should not respond if the path is not defined', function(done){ var app = express(); app.get('/users', function(req, res){}); request(app) .options('/other') .expect(404, done); }) it('should forward requests down the middleware chain', function(done){ var app = express(); var router = new express.Router(); router.get('/users', function(req, res){}); app.use(router); app.get('/other', function(req, res){}); request(app) .options('/other') .expect('GET') .expect('Allow', 'GET', done); }) }) describe('app.options()', function(){ it('should override the default behavior', function(done){ var app = express(); app.options('/users', function(req, res){ res.set('Allow', 'GET'); res.send('GET'); }); app.get('/users', function(req, res){}); app.put('/users', function(req, res){}); request(app) .options('/users') .expect('GET') .expect('Allow', 'GET', done); }) }) 4.1.1~dfsg/test/fixtures/ 0000755 0000000 0000000 00000000000 12327313561 014112 5 ustar root root 4.1.1~dfsg/test/fixtures/blog/ 0000755 0000000 0000000 00000000000 12327313561 015035 5 ustar root root 4.1.1~dfsg/test/fixtures/blog/post/ 0000755 0000000 0000000 00000000000 12327313561 016022 5 ustar root root 4.1.1~dfsg/test/fixtures/blog/post/index.jade 0000644 0000000 0000000 00000000014 12327313561 017751 0 ustar root root h1 blog post 4.1.1~dfsg/test/fixtures/pet.jade 0000644 0000000 0000000 00000000042 12327313561 015523 0 ustar root root p #{first} #{last} is a #{species} 4.1.1~dfsg/test/fixtures/user.html 0000644 0000000 0000000 00000000024 12327313561 015752 0 ustar root root{{user.name}}