4.1.1~dfsg/0000755000000000000000000000000012327313561011262 5ustar rootroot4.1.1~dfsg/Readme.md0000644000000000000000000000667712327313561013021 0ustar rootroot[![express logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/) Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). [![Build Status](https://travis-ci.org/visionmedia/express.svg?branch=master)](https://travis-ci.org/visionmedia/express) [![Gittip](https://img.shields.io/gittip/visionmedia.svg)](https://www.gittip.com/visionmedia/) ```js var express = require('express'); var app = express(); app.get('/', function(req, res){ res.send('Hello World'); }); app.listen(3000); ``` **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/visionmedia/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/visionmedia/express/wiki/New-features-in-4.x). ## Installation $ npm install express ## Quick Start The quickest way to get started with express is to utilize the executable [`express(1)`](http://github.com/expressjs/generator) to generate an application as shown below: Install the executable. The executable's major version will match Express's: $ npm install -g express-generator@3 Create the app: $ express /tmp/foo && cd /tmp/foo Install dependencies: $ npm install Start the server: $ npm start ## Features * Robust routing * HTTP helpers (redirection, caching, etc) * View system supporting 14+ template engines * Content negotiation * Focus on high performance * Executable for generating applications quickly * High test coverage ## Philosophy The Express philosophy is to provide small, robust tooling for HTTP servers, making it a great solution for single page applications, web sites, hybrids, or public HTTP APIs. Express does not force you to use any specific ORM or template engine. With support for over 14 template engines via [Consolidate.js](http://github.com/visionmedia/consolidate.js), you can quickly craft your perfect framework. ## More Information * [Website and Documentation](http://expressjs.com/) stored at [visionmedia/expressjs.com](https://github.com/visionmedia/expressjs.com) * Join #express on freenode * [Google Group](http://groups.google.com/group/express-js) for discussion * Follow [tjholowaychuk](http://twitter.com/tjholowaychuk) and [defunctzombie](https://twitter.com/defunctzombie) on twitter for updates * Visit the [Wiki](http://github.com/visionmedia/express/wiki) * [Русскоязычная документация](http://jsman.ru/express/) * Run express examples [online](https://runnable.com/express) ## Viewing Examples Clone the Express repo, then install the dev dependencies to install all the example / test suite dependencies: $ git clone git://github.com/visionmedia/express.git --depth 1 $ cd express $ npm install Then run whichever tests you want: $ node examples/content-negotiation You can also view live examples here: ## Running Tests To run the test suite, first invoke the following command within the repo, installing the development dependencies: $ npm install Then run the tests: $ make test ## Contributors Author: [TJ Holowaychuk](http://github.com/visionmedia) Lead Maintainer: [Roman Shtylman](https://github.com/defunctzombie) Contributors: https://github.com/visionmedia/express/graphs/contributors ## License MIT 4.1.1~dfsg/lib/0000755000000000000000000000000012327313561012030 5ustar rootroot4.1.1~dfsg/lib/request.js0000644000000000000000000002213712327313561014063 0ustar rootroot/** * Module dependencies. */ var accepts = require('accepts'); var typeis = require('type-is'); var http = require('http'); var fresh = require('fresh'); var parseRange = require('range-parser'); var parse = require('parseurl'); /** * Request prototype. */ var req = exports = module.exports = { __proto__: http.IncomingMessage.prototype }; /** * Return request header. * * The `Referrer` header field is special-cased, * both `Referrer` and `Referer` are interchangeable. * * Examples: * * req.get('Content-Type'); * // => "text/plain" * * req.get('content-type'); * // => "text/plain" * * req.get('Something'); * // => undefined * * Aliased as `req.header()`. * * @param {String} name * @return {String} * @api public */ req.get = req.header = function(name){ switch (name = name.toLowerCase()) { case 'referer': case 'referrer': return this.headers.referrer || this.headers.referer; default: return this.headers[name]; } }; /** * To do: update docs. * * Check if the given `type(s)` is acceptable, returning * the best match when true, otherwise `undefined`, in which * case you should respond with 406 "Not Acceptable". * * The `type` value may be a single mime type string * such as "application/json", the extension name * such as "json", a comma-delimted list such as "json, html, text/plain", * an argument list such as `"json", "html", "text/plain"`, * or an array `["json", "html", "text/plain"]`. When a list * or array is given the _best_ match, if any is returned. * * Examples: * * // Accept: text/html * req.accepts('html'); * // => "html" * * // Accept: text/*, application/json * req.accepts('html'); * // => "html" * req.accepts('text/html'); * // => "text/html" * req.accepts('json, text'); * // => "json" * req.accepts('application/json'); * // => "application/json" * * // Accept: text/*, application/json * req.accepts('image/png'); * req.accepts('png'); * // => undefined * * // Accept: text/*;q=.5, application/json * req.accepts(['html', 'json']); * req.accepts('html', 'json'); * req.accepts('html, json'); * // => "json" * * @param {String|Array} type(s) * @return {String} * @api public */ req.accepts = function(){ var accept = accepts(this); return accept.types.apply(accept, arguments); }; /** * Check if the given `encoding` is accepted. * * @param {String} encoding * @return {Boolean} * @api public */ req.acceptsEncoding = // backwards compatibility req.acceptsEncodings = function(){ var accept = accepts(this); return accept.encodings.apply(accept, arguments); }; /** * To do: update docs. * * Check if the given `charset` is acceptable, * otherwise you should respond with 406 "Not Acceptable". * * @param {String} charset * @return {Boolean} * @api public */ req.acceptsCharset = // backwards compatibility req.acceptsCharsets = function(){ var accept = accepts(this); return accept.charsets.apply(accept, arguments); }; /** * To do: update docs. * * Check if the given `lang` is acceptable, * otherwise you should respond with 406 "Not Acceptable". * * @param {String} lang * @return {Boolean} * @api public */ req.acceptsLanguage = // backwards compatibility req.acceptsLanguages = function(){ var accept = accepts(this); return accept.languages.apply(accept, arguments); }; /** * Parse Range header field, * capping to the given `size`. * * Unspecified ranges such as "0-" require * knowledge of your resource length. In * the case of a byte range this is of course * the total number of bytes. If the Range * header field is not given `null` is returned, * `-1` when unsatisfiable, `-2` when syntactically invalid. * * NOTE: remember that ranges are inclusive, so * for example "Range: users=0-3" should respond * with 4 users when available, not 3. * * @param {Number} size * @return {Array} * @api public */ req.range = function(size){ var range = this.get('Range'); if (!range) return; return parseRange(size, range); }; /** * Return the value of param `name` when present or `defaultValue`. * * - Checks route placeholders, ex: _/user/:id_ * - Checks body params, ex: id=12, {"id":12} * - Checks query string params, ex: ?id=12 * * To utilize request bodies, `req.body` * should be an object. This can be done by using * the `bodyParser()` middleware. * * @param {String} name * @param {Mixed} [defaultValue] * @return {String} * @api public */ req.param = function(name, defaultValue){ var params = this.params || {}; var body = this.body || {}; var query = this.query || {}; if (null != params[name] && params.hasOwnProperty(name)) return params[name]; if (null != body[name]) return body[name]; if (null != query[name]) return query[name]; return defaultValue; }; /** * Check if the incoming request contains the "Content-Type" * header field, and it contains the give mime `type`. * * Examples: * * // With Content-Type: text/html; charset=utf-8 * req.is('html'); * req.is('text/html'); * req.is('text/*'); * // => true * * // When Content-Type is application/json * req.is('json'); * req.is('application/json'); * req.is('application/*'); * // => true * * req.is('html'); * // => false * * @param {String} type * @return {Boolean} * @api public */ req.is = function(types){ if (!Array.isArray(types)) types = [].slice.call(arguments); return typeis(this, types); }; /** * Return the protocol string "http" or "https" * when requested with TLS. When the "trust proxy" * setting is enabled the "X-Forwarded-Proto" header * field will be trusted. If you're running behind * a reverse proxy that supplies https for you this * may be enabled. * * @return {String} * @api public */ req.__defineGetter__('protocol', function(){ var trustProxy = this.app.get('trust proxy'); if (this.connection.encrypted) return 'https'; if (!trustProxy) return 'http'; var proto = this.get('X-Forwarded-Proto') || 'http'; return proto.split(/\s*,\s*/)[0]; }); /** * Short-hand for: * * req.protocol == 'https' * * @return {Boolean} * @api public */ req.__defineGetter__('secure', function(){ return 'https' == this.protocol; }); /** * Return the remote address, or when * "trust proxy" is `true` return * the upstream addr. * * @return {String} * @api public */ req.__defineGetter__('ip', function(){ return this.ips[0] || this.connection.remoteAddress; }); /** * When "trust proxy" is `true`, parse * the "X-Forwarded-For" ip address list. * * For example if the value were "client, proxy1, proxy2" * you would receive the array `["client", "proxy1", "proxy2"]` * where "proxy2" is the furthest down-stream. * * @return {Array} * @api public */ req.__defineGetter__('ips', function(){ var trustProxy = this.app.get('trust proxy'); var val = this.get('X-Forwarded-For'); return trustProxy && val ? val.split(/ *, */) : []; }); /** * Return subdomains as an array. * * Subdomains are the dot-separated parts of the host before the main domain of * the app. By default, the domain of the app is assumed to be the last two * parts of the host. This can be changed by setting "subdomain offset". * * For example, if the domain is "tobi.ferrets.example.com": * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`. * If "subdomain offset" is 3, req.subdomains is `["tobi"]`. * * @return {Array} * @api public */ req.__defineGetter__('subdomains', function(){ var offset = this.app.get('subdomain offset'); return (this.host || '') .split('.') .reverse() .slice(offset); }); /** * Short-hand for `url.parse(req.url).pathname`. * * @return {String} * @api public */ req.__defineGetter__('path', function(){ return parse(this).pathname; }); /** * Parse the "Host" header field hostname. * * @return {String} * @api public */ req.__defineGetter__('host', function(){ var trustProxy = this.app.get('trust proxy'); var host = trustProxy && this.get('X-Forwarded-Host'); host = host || this.get('Host'); if (!host) return; return host.split(':')[0]; }); /** * Check if the request is fresh, aka * Last-Modified and/or the ETag * still match. * * @return {Boolean} * @api public */ req.__defineGetter__('fresh', function(){ var method = this.method; var s = this.res.statusCode; // GET or HEAD for weak freshness validation only if ('GET' != method && 'HEAD' != method) return false; // 2xx or 304 as per rfc2616 14.26 if ((s >= 200 && s < 300) || 304 == s) { return fresh(this.headers, this.res._headers); } return false; }); /** * Check if the request is stale, aka * "Last-Modified" and / or the "ETag" for the * resource has changed. * * @return {Boolean} * @api public */ req.__defineGetter__('stale', function(){ return !this.fresh; }); /** * Check if the request was an _XMLHttpRequest_. * * @return {Boolean} * @api public */ req.__defineGetter__('xhr', function(){ var val = this.get('X-Requested-With') || ''; return 'xmlhttprequest' == val.toLowerCase(); }); 4.1.1~dfsg/lib/view.js0000644000000000000000000000344212327313561013343 0ustar rootroot/** * Module dependencies. */ var path = require('path'); var fs = require('fs'); var utils = require('./utils'); var dirname = path.dirname; var basename = path.basename; var extname = path.extname; var exists = fs.existsSync || path.existsSync; var join = path.join; /** * Expose `View`. */ module.exports = View; /** * Initialize a new `View` with the given `name`. * * Options: * * - `defaultEngine` the default template engine name * - `engines` template engine require() cache * - `root` root path for view lookup * * @param {String} name * @param {Object} options * @api private */ function View(name, options) { options = options || {}; this.name = name; this.root = options.root; var engines = options.engines; this.defaultEngine = options.defaultEngine; var ext = this.ext = extname(name); if (!ext && !this.defaultEngine) throw new Error('No default engine was specified and no extension was provided.'); if (!ext) name += (ext = this.ext = ('.' != this.defaultEngine[0] ? '.' : '') + this.defaultEngine); this.engine = engines[ext] || (engines[ext] = require(ext.slice(1)).__express); this.path = this.lookup(name); } /** * Lookup view by the given `path` * * @param {String} path * @return {String} * @api private */ View.prototype.lookup = function(path){ var ext = this.ext; // . if (!utils.isAbsolute(path)) path = join(this.root, path); if (exists(path)) return path; // /index. path = join(dirname(path), basename(path, ext), 'index' + ext); if (exists(path)) return path; }; /** * Render with the given `options` and callback `fn(err, str)`. * * @param {Object} options * @param {Function} fn * @api private */ View.prototype.render = function(options, fn){ this.engine(this.path, options, fn); }; 4.1.1~dfsg/lib/application.js0000644000000000000000000002741512327313561014702 0ustar rootroot/** * Module dependencies. */ var mixin = require('utils-merge'); var escapeHtml = require('escape-html'); var Router = require('./router'); var methods = require('methods'); var middleware = require('./middleware/init'); var query = require('./middleware/query'); var debug = require('debug')('express:application'); var View = require('./view'); var http = require('http'); /** * Application prototype. */ var app = exports = module.exports = {}; /** * Initialize the server. * * - setup default configuration * - setup default middleware * - setup route reflection methods * * @api private */ app.init = function(){ this.cache = {}; this.settings = {}; this.engines = {}; this.defaultConfiguration(); }; /** * Initialize application configuration. * * @api private */ app.defaultConfiguration = function(){ // default settings this.enable('x-powered-by'); this.enable('etag'); var env = process.env.NODE_ENV || 'development'; this.set('env', env); this.set('subdomain offset', 2); debug('booting in %s mode', env); // inherit protos this.on('mount', function(parent){ this.request.__proto__ = parent.request; this.response.__proto__ = parent.response; this.engines.__proto__ = parent.engines; this.settings.__proto__ = parent.settings; }); // setup locals this.locals = Object.create(null); // top-most app is mounted at / this.mountpath = '/'; // default locals this.locals.settings = this.settings; // default configuration this.set('view', View); this.set('views', process.cwd() + '/views'); this.set('jsonp callback name', 'callback'); if (env === 'production') { this.enable('view cache'); } Object.defineProperty(this, 'router', { get: function() { throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.'); } }); }; /** * lazily adds the base router if it has not yet been added. * * We cannot add the base router in the defaultConfiguration because * it reads app settings which might be set after that has run. * * @api private */ app.lazyrouter = function() { if (!this._router) { this._router = new Router({ caseSensitive: this.enabled('case sensitive routing'), strict: this.enabled('strict routing') }); this._router.use(query()); this._router.use(middleware.init(this)); } }; /** * Dispatch a req, res pair into the application. Starts pipeline processing. * * If no _done_ callback is provided, then default error handlers will respond * in the event of an error bubbling through the stack. * * @api private */ app.handle = function(req, res, done) { var env = this.get('env'); this._router.handle(req, res, function(err) { if (done) { return done(err); } // unhandled error if (err) { // default to 500 if (res.statusCode < 400) res.statusCode = 500; debug('default %s', res.statusCode); // respect err.status if (err.status) res.statusCode = err.status; // production gets a basic error message var msg = 'production' == env ? http.STATUS_CODES[res.statusCode] : err.stack || err.toString(); msg = escapeHtml(msg); // log to stderr in a non-test env if ('test' != env) console.error(err.stack || err.toString()); if (res.headersSent) return req.socket.destroy(); res.setHeader('Content-Type', 'text/html'); res.setHeader('Content-Length', Buffer.byteLength(msg)); if ('HEAD' == req.method) return res.end(); res.end(msg); return; } // 404 debug('default 404'); res.statusCode = 404; res.setHeader('Content-Type', 'text/html'); if ('HEAD' == req.method) return res.end(); res.end('Cannot ' + escapeHtml(req.method) + ' ' + escapeHtml(req.originalUrl) + '\n'); }); }; /** * Proxy `Router#use()` to add middleware to the app router. * See Router#use() documentation for details. * * If the _fn_ parameter is an express app, then it will be * mounted at the _route_ specified. * * @param {String|Function|Server} route * @param {Function|Server} fn * @return {app} for chaining * @api public */ app.use = function(route, fn){ var mount_app; // default route to '/' if ('string' != typeof route) fn = route, route = '/'; // express app if (fn.handle && fn.set) mount_app = fn; // restore .app property on req and res if (mount_app) { debug('.use app under %s', route); mount_app.mountpath = route; fn = function(req, res, next) { var orig = req.app; mount_app.handle(req, res, function(err) { req.__proto__ = orig.request; res.__proto__ = orig.response; next(err); }); }; } this.lazyrouter(); this._router.use(route, fn); // mounted an app if (mount_app) { mount_app.parent = this; mount_app.emit('mount', this); } return this; }; /** * Proxy to the app `Router#route()` * Returns a new `Route` instance for the _path_. * * Routes are isolated middleware stacks for specific paths. * See the Route api docs for details. * * @api public */ app.route = function(path){ this.lazyrouter(); return this._router.route(path); }; /** * Register the given template engine callback `fn` * as `ext`. * * By default will `require()` the engine based on the * file extension. For example if you try to render * a "foo.jade" file Express will invoke the following internally: * * app.engine('jade', require('jade').__express); * * For engines that do not provide `.__express` out of the box, * or if you wish to "map" a different extension to the template engine * you may use this method. For example mapping the EJS template engine to * ".html" files: * * app.engine('html', require('ejs').renderFile); * * In this case EJS provides a `.renderFile()` method with * the same signature that Express expects: `(path, options, callback)`, * though note that it aliases this method as `ejs.__express` internally * so if you're using ".ejs" extensions you dont need to do anything. * * Some template engines do not follow this convention, the * [Consolidate.js](https://github.com/visionmedia/consolidate.js) * library was created to map all of node's popular template * engines to follow this convention, thus allowing them to * work seamlessly within Express. * * @param {String} ext * @param {Function} fn * @return {app} for chaining * @api public */ app.engine = function(ext, fn){ if ('function' != typeof fn) throw new Error('callback function required'); if ('.' != ext[0]) ext = '.' + ext; this.engines[ext] = fn; return this; }; /** * Proxy to `Router#param()` with one added api feature. The _name_ parameter * can be an array of names. * * See the Router#param() docs for more details. * * @param {String|Array} name * @param {Function} fn * @return {app} for chaining * @api public */ app.param = function(name, fn){ var self = this; self.lazyrouter(); if (Array.isArray(name)) { name.forEach(function(key) { self.param(key, fn); }); return this; } self._router.param(name, fn); return this; }; /** * Assign `setting` to `val`, or return `setting`'s value. * * app.set('foo', 'bar'); * app.get('foo'); * // => "bar" * * Mounted servers inherit their parent server's settings. * * @param {String} setting * @param {*} [val] * @return {Server} for chaining * @api public */ app.set = function(setting, val){ if (1 == arguments.length) { return this.settings[setting]; } else { this.settings[setting] = val; return this; } }; /** * Return the app's absolute pathname * based on the parent(s) that have * mounted it. * * For example if the application was * mounted as "/admin", which itself * was mounted as "/blog" then the * return value would be "/blog/admin". * * @return {String} * @api private */ app.path = function(){ return this.parent ? this.parent.path() + this.mountpath : ''; }; /** * Check if `setting` is enabled (truthy). * * app.enabled('foo') * // => false * * app.enable('foo') * app.enabled('foo') * // => true * * @param {String} setting * @return {Boolean} * @api public */ app.enabled = function(setting){ return !!this.set(setting); }; /** * Check if `setting` is disabled. * * app.disabled('foo') * // => true * * app.enable('foo') * app.disabled('foo') * // => false * * @param {String} setting * @return {Boolean} * @api public */ app.disabled = function(setting){ return !this.set(setting); }; /** * Enable `setting`. * * @param {String} setting * @return {app} for chaining * @api public */ app.enable = function(setting){ return this.set(setting, true); }; /** * Disable `setting`. * * @param {String} setting * @return {app} for chaining * @api public */ app.disable = function(setting){ return this.set(setting, false); }; /** * Delegate `.VERB(...)` calls to `router.VERB(...)`. */ methods.forEach(function(method){ app[method] = function(path){ if ('get' == method && 1 == arguments.length) return this.set(path); this.lazyrouter(); var route = this._router.route(path); route[method].apply(route, [].slice.call(arguments, 1)); return this; }; }); /** * Special-cased "all" method, applying the given route `path`, * middleware, and callback to _every_ HTTP method. * * @param {String} path * @param {Function} ... * @return {app} for chaining * @api public */ app.all = function(path){ this.lazyrouter(); var route = this._router.route(path); var args = [].slice.call(arguments, 1); methods.forEach(function(method){ route[method].apply(route, args); }); return this; }; // del -> delete alias app.del = app.delete; /** * Render the given view `name` name with `options` * and a callback accepting an error and the * rendered template string. * * Example: * * app.render('email', { name: 'Tobi' }, function(err, html){ * // ... * }) * * @param {String} name * @param {String|Function} options or fn * @param {Function} fn * @api public */ app.render = function(name, options, fn){ var opts = {}; var cache = this.cache; var engines = this.engines; var view; // support callback function as second arg if ('function' == typeof options) { fn = options, options = {}; } // merge app.locals mixin(opts, this.locals); // merge options._locals if (options._locals) mixin(opts, options._locals); // merge options mixin(opts, options); // set .cache unless explicitly provided opts.cache = null == opts.cache ? this.enabled('view cache') : opts.cache; // primed cache if (opts.cache) view = cache[name]; // view if (!view) { view = new (this.get('view'))(name, { defaultEngine: this.get('view engine'), root: this.get('views'), engines: engines }); if (!view.path) { var err = new Error('Failed to lookup view "' + name + '" in views directory "' + view.root + '"'); err.view = view; return fn(err); } // prime the cache if (opts.cache) cache[name] = view; } // render try { view.render(opts, fn); } catch (err) { fn(err); } }; /** * Listen for connections. * * A node `http.Server` is returned, with this * application (which is a `Function`) as its * callback. If you wish to create both an HTTP * and HTTPS server you may do so with the "http" * and "https" modules as shown here: * * var http = require('http') * , https = require('https') * , express = require('express') * , app = express(); * * http.createServer(app).listen(80); * https.createServer({ ... }, app).listen(443); * * @return {http.Server} * @api public */ app.listen = function(){ var server = http.createServer(this); return server.listen.apply(server, arguments); }; 4.1.1~dfsg/lib/response.js0000644000000000000000000004335512327313561014236 0ustar rootroot/** * Module dependencies. */ var http = require('http'); var path = require('path'); var mixin = require('utils-merge'); var escapeHtml = require('escape-html'); var sign = require('cookie-signature').sign; var normalizeType = require('./utils').normalizeType; var normalizeTypes = require('./utils').normalizeTypes; var contentDisposition = require('./utils').contentDisposition; var etag = require('./utils').etag; var statusCodes = http.STATUS_CODES; var cookie = require('cookie'); var send = require('send'); var basename = path.basename; var extname = path.extname; var mime = send.mime; /** * Response prototype. */ var res = module.exports = { __proto__: http.ServerResponse.prototype }; /** * Set status `code`. * * @param {Number} code * @return {ServerResponse} * @api public */ res.status = function(code){ this.statusCode = code; return this; }; /** * Set Link header field with the given `links`. * * Examples: * * res.links({ * next: 'http://api.example.com/users?page=2', * last: 'http://api.example.com/users?page=5' * }); * * @param {Object} links * @return {ServerResponse} * @api public */ res.links = function(links){ var link = this.get('Link') || ''; if (link) link += ', '; return this.set('Link', link + Object.keys(links).map(function(rel){ return '<' + links[rel] + '>; rel="' + rel + '"'; }).join(', ')); }; /** * Send a response. * * Examples: * * res.send(new Buffer('wahoo')); * res.send({ some: 'json' }); * res.send('

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.js0000644000000000000000000000540612327313561013533 0ustar rootroot/** * 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.js0000644000000000000000000000333112327313561014057 0ustar rootroot/** * 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/0000755000000000000000000000000012327313561013350 5ustar rootroot4.1.1~dfsg/lib/router/route.js0000644000000000000000000000731212327313561015047 0ustar rootroot/** * 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.js0000644000000000000000000000226512327313561015027 0ustar rootroot/** * 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.js0000644000000000000000000002152412327313561015021 0ustar rootroot/** * 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/0000755000000000000000000000000012327313561014145 5ustar rootroot4.1.1~dfsg/lib/middleware/init.js0000644000000000000000000000107212327313561015446 0ustar rootroot/** * 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.js0000644000000000000000000000141612327313561015652 0ustar rootroot/** * 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.json0000644000000000000000000000363412327313561013556 0ustar rootroot{ "name": "express", "description": "Sinatra inspired web development framework", "version": "4.1.1", "author": "TJ Holowaychuk ", "contributors": [ { "name": "TJ Holowaychuk", "email": "tj@vision-media.ca" }, { "name": "Aaron Heckmann", "email": "aaron.heckmann+github@gmail.com" }, { "name": "Ciaran Jessup", "email": "ciaranj@gmail.com" }, { "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }, { "name": "Jonathan Ong", "email": "me@jongleberry.com" }, { "name": "Roman Shtylman", "email": "shtylman+expressjs@gmail.com" } ], "dependencies": { "parseurl": "1.0.1", "accepts": "1.0.1", "type-is": "1.1.0", "range-parser": "1.0.0", "cookie": "0.1.2", "buffer-crc32": "0.2.1", "fresh": "0.2.2", "methods": "0.1.0", "send": "0.3.0", "cookie-signature": "1.0.3", "merge-descriptors": "0.0.2", "utils-merge": "1.0.0", "escape-html": "1.0.1", "qs": "0.6.6", "serve-static": "1.1.0", "path-to-regexp": "0.1.2", "debug": ">= 0.7.3 < 1" }, "devDependencies": { "mocha": "~1.18.2", "body-parser": "1.0.2", "connect-redis": "~2.0.0", "ejs": "~1.0.0", "express-session": "1.0.3", "jade": "~0.35.0", "marked": "0.3.2", "multiparty": "~3.2.4", "static-favicon": "1.0.2", "hjs": "~0.0.6", "should": "~3.3.1", "supertest": "~0.11.0", "method-override": "1.0.0", "cookie-parser": "1.0.1", "morgan": "1.0.0", "vhost": "1.0.0" }, "keywords": [ "express", "framework", "sinatra", "web", "rest", "restful", "router", "app", "api" ], "repository": "git://github.com/visionmedia/express", "scripts": { "prepublish": "npm prune", "test": "make test" }, "engines": { "node": ">= 0.10.0" }, "license": "MIT" } 4.1.1~dfsg/Makefile0000644000000000000000000000112612327313561012722 0ustar rootroot MOCHA_OPTS= --check-leaks REPORTER = dot check: test test: test-unit test-acceptance test-unit: @NODE_ENV=test ./node_modules/.bin/mocha \ --reporter $(REPORTER) \ --globals setImmediate,clearImmediate \ $(MOCHA_OPTS) test-acceptance: @NODE_ENV=test ./node_modules/.bin/mocha \ --reporter $(REPORTER) \ --bail \ test/acceptance/*.js test-cov: lib-cov @EXPRESS_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html lib-cov: @jscoverage lib lib-cov bench: @$(MAKE) -C benchmarks clean: rm -f coverage.html rm -fr lib-cov .PHONY: test test-unit test-acceptance bench clean 4.1.1~dfsg/LICENSE0000644000000000000000000000211712327313561012270 0ustar rootroot(The MIT License) Copyright (c) 2009-2014 TJ Holowaychuk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 4.1.1~dfsg/.npmignore0000644000000000000000000000015012327313561013255 0ustar rootroot.git* benchmarks/ docs/ examples/ support/ test/ testing.js .DS_Store .travis.yml coverage.html lib-cov 4.1.1~dfsg/support/0000755000000000000000000000000012327313561012776 5ustar rootroot4.1.1~dfsg/support/app.js0000644000000000000000000000215612327313561014120 0ustar rootroot /** * Module dependencies. */ var express = require('../'); var app = express() , blog = express() , admin = express(); blog.use('/admin', admin); app.use('/blog', blog); app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.locals.self = true; app.get('/render', function(req, res){ res.render('hello'); }); admin.get('/', function(req, res){ res.send('Hello World\n'); }); blog.get('/', function(req, res){ res.send('Hello World\n'); }); app.get('/', function(req, res){ res.send('Hello World\n'); }); app.get('/json', function(req, res){ res.send({ name: 'Tobi', role: 'admin' }); }); app.get('/json/:n', function(req, res){ var n = ~~req.params.n; var arr = []; var obj = { name: 'Tobi', role: 'admin' }; while (n--) arr.push(obj); res.send(arr); }); function foo(req, res, next) { next(); } app.get('/middleware', foo, foo, foo, foo, function(req, res){ res.send('Hello World\n'); }); var n = 100; while (n--) { app.get('/foo', foo, foo, function(req, res){ }); } app.get('/match', function(req, res){ res.send('Hello World\n'); }); app.listen(8000); 4.1.1~dfsg/support/views/0000755000000000000000000000000012327313561014133 5ustar rootroot4.1.1~dfsg/support/views/hello.jade0000644000000000000000000000000712327313561016060 0ustar rootrootp Hello4.1.1~dfsg/test/0000755000000000000000000000000012327313561012241 5ustar rootroot4.1.1~dfsg/test/res.render.js0000644000000000000000000001446512327313561014660 0ustar rootroot var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.render(name)', function(){ it('should support absolute paths', function(done){ var app = express(); app.locals.user = { name: 'tobi' }; app.use(function(req, res){ res.render(__dirname + '/fixtures/user.jade'); }); request(app) .get('/') .expect('

tobi

', 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.', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.set('view engine', 'jade'); app.use(function(req, res){ res.render('blog/post'); }); request(app) .get('/') .expect('

blog post

', done); }) describe('when an error occurs', function(){ it('should next(err)', function(done){ var app = express(); app.set('views', __dirname + '/fixtures'); app.use(function(req, res){ res.render('user.jade'); }); app.use(function(err, req, res, next){ res.end(err.message); }); request(app) .get('/') .expect(/Cannot read property '[^']+' of undefined/, done); }) }) describe('when "view engine" is given', function(){ it('should render the template', function(done){ var app = express(); app.set('view engine', 'jade'); app.set('views', __dirname + '/fixtures'); app.use(function(req, res){ res.render('email'); }); request(app) .get('/') .expect('

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.js0000644000000000000000000000147712327313561014155 0ustar rootroot 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.js0000644000000000000000000000165412327313561016161 0ustar rootroot 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.js0000644000000000000000000000176712327313561015622 0ustar rootroot 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.js0000644000000000000000000000125212327313561014126 0ustar rootroot 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.js0000644000000000000000000001474012327313561015166 0ustar rootroot 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.js0000644000000000000000000000241412327313561014466 0ustar rootroot 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.js0000644000000000000000000000416412327313561014005 0ustar rootroot 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.js0000644000000000000000000001133212327313561014057 0ustar rootroot 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.js0000644000000000000000000000110012327313561014513 0ustar rootroot 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.js0000644000000000000000000000063312327313561014714 0ustar rootroot 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.js0000644000000000000000000003206012327313561014677 0ustar rootroot 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.js0000644000000000000000000000207512327313561016033 0ustar rootrootvar 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.js0000644000000000000000000000231712327313561016324 0ustar rootroot 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.js0000644000000000000000000000210212327313561014502 0ustar rootroot 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( '; rel="next", ' + '; rel="last"'); }) it('should set Link header field for multiple calls', function() { res.links({ next: 'http://api.example.com/users?page=2', last: 'http://api.example.com/users?page=5' }); res.links({ prev: 'http://api.example.com/users?page=1', }); res.get('link') .should.equal( '; rel="next", ' + '; rel="last", ' + '; rel="prev"'); }) }) }) 4.1.1~dfsg/test/req.ips.js0000644000000000000000000000252212327313561014161 0ustar rootroot var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.ips', function(){ describe('when X-Forwarded-For is present', function(){ describe('when "trust proxy" is enabled', function(){ it('should return an array of the specified addresses', function(done){ var app = express(); app.enable('trust proxy'); app.use(function(req, res, next){ res.send(req.ips); }); request(app) .get('/') .set('X-Forwarded-For', 'client, p1, p2') .expect('["client","p1","p2"]', done); }) }) describe('when "trust proxy" is disabled', function(){ it('should return an empty array', function(done){ var app = express(); app.use(function(req, res, next){ res.send(req.ips); }); request(app) .get('/') .set('X-Forwarded-For', 'client, p1, p2') .expect('[]', done); }) }) }) describe('when X-Forwarded-For is not present', function(){ it('should return []', function(done){ var app = express(); app.use(function(req, res, next){ res.send(req.ips); }); request(app) .get('/') .expect('[]', done); }) }) }) }) 4.1.1~dfsg/test/mocha.opts0000644000000000000000000000004312327313561014234 0ustar rootroot--require should --slow 20 --growl 4.1.1~dfsg/test/res.get.js0000644000000000000000000000065012327313561014147 0ustar rootroot var express = require('../') , res = express.response; describe('res', function(){ describe('.get(field)', function(){ it('should get the response header field', function(){ res.setHeader('Content-Type', 'text/x-foo'); res.get('Content-Type').should.equal('text/x-foo'); res.get('Content-type').should.equal('text/x-foo'); res.get('content-type').should.equal('text/x-foo'); }) }) }) 4.1.1~dfsg/test/req.query.js0000644000000000000000000000132412327313561014532 0ustar rootroot var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.query', function(){ it('should default to {}', function(done){ var app = express(); app.use(function(req, res){ req.query.should.eql({}); res.end(); }); request(app) .get('/') .end(function(res){ done(); }); }) it('should contain the parsed query-string', function(done){ var app = express(); app.use(function(req, res){ req.query.should.eql({ user: { name: 'tj' }}); res.end(); }); request(app) .get('/?user[name]=tj') .end(function(res){ done(); }); }) }) }) 4.1.1~dfsg/test/res.redirect.js0000644000000000000000000001102612327313561015170 0ustar rootroot var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.redirect(url)', function(){ it('should default to a 302 redirect', function(done){ var app = express(); app.use(function(req, res){ res.redirect('http://google.com'); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(302); res.headers.should.have.property('location', 'http://google.com'); done(); }) }) }) describe('.redirect(status, url)', function(){ it('should set the response status', function(done){ var app = express(); app.use(function(req, res){ res.redirect(303, 'http://google.com'); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(303); res.headers.should.have.property('location', 'http://google.com'); done(); }) }) }) describe('.redirect(url, status)', function(){ it('should set the response status', function(done){ var app = express(); app.use(function(req, res){ res.redirect('http://google.com', 303); }); request(app) .get('/') .end(function(err, res){ res.statusCode.should.equal(303); res.headers.should.have.property('location', 'http://google.com'); 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.redirect('http://google.com'); }); request(app) .head('/') .end(function(err, res){ res.headers.should.have.property('location', 'http://google.com'); res.text.should.equal(''); done(); }) }) }) describe('when accepting html', function(){ it('should respond with html', function(done){ var app = express(); app.use(function(req, res){ res.redirect('http://google.com'); }); request(app) .get('/') .set('Accept', 'text/html') .end(function(err, res){ res.headers.should.have.property('location', 'http://google.com'); res.text.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(''); }); request(app) .get('/') .set('Host', 'http://example.com') .set('Accept', 'text/html') .end(function(err, res){ res.text.should.equal('

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.js0000644000000000000000000001062712327313561014346 0ustar rootroot 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.js0000644000000000000000000000407712327313561014633 0ustar rootroot 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.js0000644000000000000000000001055012327313561014641 0ustar rootroot 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.js0000644000000000000000000000220012327313561013731 0ustar rootroot 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.js0000644000000000000000000000173412327313561014521 0ustar rootrootvar 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.js0000644000000000000000000000642212327313561014663 0ustar rootroot 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.js0000644000000000000000000001500312327313561014517 0ustar rootroot 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.js0000644000000000000000000000370612327313561013365 0ustar rootroot 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.js0000644000000000000000000000357612327313561015532 0ustar rootroot 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.js0000644000000000000000000000144212327313561014634 0ustar rootroot 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.js0000644000000000000000000000212212327313561015771 0ustar rootroot 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.js0000644000000000000000000000052212327313561014121 0ustar rootroot 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.js0000644000000000000000000000256212327313561014002 0ustar rootroot 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.js0000644000000000000000000000373512327313561014172 0ustar rootroot 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.js0000644000000000000000000000260412327313561015230 0ustar rootroot 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.js0000644000000000000000000000074712327313561015207 0ustar rootroot 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.js0000644000000000000000000000061712327313561014325 0ustar rootroot 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.js0000644000000000000000000000701012327313561013673 0ustar rootroot 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.js0000644000000000000000000000140412327313561014643 0ustar rootroot 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.js0000644000000000000000000000257712327313561014363 0ustar rootroot 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.js0000644000000000000000000000055412327313561014763 0ustar rootroot 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.js0000644000000000000000000000453312327313561014051 0ustar rootroot 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.js0000644000000000000000000000132012327313561014336 0ustar rootroot 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.js0000644000000000000000000000243712327313561014311 0ustar rootroot 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.js0000644000000000000000000002203112327313561014316 0ustar rootroot 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.js0000644000000000000000000000077112327313561015053 0ustar rootroot 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.js0000644000000000000000000000055612327313561014662 0ustar rootroot 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.js0000644000000000000000000000260512327313561015054 0ustar rootroot 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/0000755000000000000000000000000012327313561014112 5ustar rootroot4.1.1~dfsg/test/fixtures/blog/0000755000000000000000000000000012327313561015035 5ustar rootroot4.1.1~dfsg/test/fixtures/blog/post/0000755000000000000000000000000012327313561016022 5ustar rootroot4.1.1~dfsg/test/fixtures/blog/post/index.jade0000644000000000000000000000001412327313561017751 0ustar rootrooth1 blog post4.1.1~dfsg/test/fixtures/pet.jade0000644000000000000000000000004212327313561015523 0ustar rootrootp #{first} #{last} is a #{species}4.1.1~dfsg/test/fixtures/user.html0000644000000000000000000000002412327313561015752 0ustar rootroot

{{user.name}}

4.1.1~dfsg/test/fixtures/email.jade0000644000000000000000000000002212327313561016020 0ustar rootrootp This is an email4.1.1~dfsg/test/fixtures/.name0000644000000000000000000000000412327313561015025 0ustar rootroottobi4.1.1~dfsg/test/fixtures/name.txt0000644000000000000000000000000412327313561015565 0ustar rootroottobi4.1.1~dfsg/test/fixtures/name.jade0000644000000000000000000000001012327313561015646 0ustar rootrootp= name 4.1.1~dfsg/test/fixtures/user.jade0000644000000000000000000000001412327313561015710 0ustar rootrootp= user.name4.1.1~dfsg/test/req.fresh.js0000644000000000000000000000141012327313561014470 0ustar rootroot var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.fresh', function(){ it('should return true when the resource is not modified', function(done){ var app = express(); app.use(function(req, res){ res.set('ETag', '12345'); res.send(req.fresh); }); request(app) .get('/') .set('If-None-Match', '12345') .expect(304, done); }) it('should return false when the resource is modified', function(done){ var app = express(); app.use(function(req, res){ res.set('ETag', '123'); res.send(req.fresh); }); request(app) .get('/') .set('If-None-Match', '12345') .expect('false', done); }) }) }) 4.1.1~dfsg/test/req.secure.js0000644000000000000000000000370612327313561014661 0ustar rootroot var express = require('../') , request = require('supertest'); describe('req', function(){ describe('.secure', function(){ describe('when X-Forwarded-Proto is missing', function(){ it('should return false when http', function(done){ var app = express(); app.get('/', function(req, res){ res.send(req.secure ? 'yes' : 'no'); }); request(app) .get('/') .expect('no', done) }) }) }) describe('.secure', function(){ describe('when X-Forwarded-Proto is present', function(){ it('should return false when http', function(done){ var app = express(); app.get('/', function(req, res){ res.send(req.secure ? 'yes' : 'no'); }); request(app) .get('/') .set('X-Forwarded-Proto', 'https') .expect('no', done) }) it('should return true when "trust proxy" is enabled', function(done){ var app = express(); app.enable('trust proxy'); app.get('/', function(req, res){ res.send(req.secure ? 'yes' : 'no'); }); request(app) .get('/') .set('X-Forwarded-Proto', 'https') .expect('yes', done) }) it('should return false when initial proxy is http', function(done){ var app = express(); app.enable('trust proxy'); app.get('/', function(req, res){ res.send(req.secure ? 'yes' : 'no'); }); request(app) .get('/') .set('X-Forwarded-Proto', 'http, https') .expect('no', done) }) it('should return true when initial proxy is https', function(done){ var app = express(); app.enable('trust proxy'); app.get('/', function(req, res){ res.send(req.secure ? 'yes' : 'no'); }); request(app) .get('/') .set('X-Forwarded-Proto', 'https, http') .expect('yes', done) }) }) }) }) 4.1.1~dfsg/test/res.type.js0000644000000000000000000000207612327313561014355 0ustar rootroot var express = require('../') , request = require('supertest'); describe('res', function(){ describe('.type(str)', function(){ it('should set the Content-Type based on a filename', function(done){ var app = express(); app.use(function(req, res){ res.type('foo.js').end('var name = "tj";'); }); request(app) .get('/') .expect('Content-Type', 'application/javascript', done); }) it('should default to application/octet-stream', function(done){ var app = express(); app.use(function(req, res){ res.type('rawr').end('var name = "tj";'); }); request(app) .get('/') .expect('Content-Type', 'application/octet-stream', done); }) it('should set the Content-Type with type/subtype', function(done){ var app = express(); app.use(function(req, res){ res.type('application/vnd.amazon.ebook') .end('var name = "tj";'); }); request(app) .get('/') .expect('Content-Type', 'application/vnd.amazon.ebook', done); }) }) }) 4.1.1~dfsg/test/app.response.js0000644000000000000000000000160012327313561015211 0ustar rootroot var express = require('../') , request = require('supertest'); describe('app', function(){ describe('.response', function(){ it('should extend the response prototype', function(done){ var app = express(); app.response.shout = function(str){ this.send(str.toUpperCase()); }; app.use(function(req, res){ res.shout('hey'); }); request(app) .get('/') .expect('HEY', done); }) it('should not be influenced by other app protos', function(done){ var app = express() , app2 = express(); app.response.shout = function(str){ this.send(str.toUpperCase()); }; app2.response.shout = function(str){ this.send(str); }; app.use(function(req, res){ res.shout('hey'); }); request(app) .get('/') .expect('HEY', done); }) }) }) 4.1.1~dfsg/test/res.download.js0000644000000000000000000000610412327313561015177 0ustar rootroot var express = require('../') , request = require('supertest') , assert = require('assert'); describe('res', function(){ describe('.download(path)', function(){ it('should transfer as an attachment', function(done){ var app = express(); app.use(function(req, res){ res.download('test/fixtures/user.html'); }); request(app) .get('/') .end(function(err, res){ res.should.have.header('Content-Type', 'text/html; charset=UTF-8'); res.should.have.header('Content-Disposition', 'attachment; filename="user.html"'); res.text.should.equal('

{{user.name}}

'); done(); }); }) }) describe('.download(path, filename)', function(){ it('should provide an alternate filename', function(done){ var app = express(); app.use(function(req, res){ res.download('test/fixtures/user.html', 'document'); }); request(app) .get('/') .end(function(err, res){ res.should.have.header('Content-Type', 'text/html; charset=UTF-8'); res.should.have.header('Content-Disposition', 'attachment; filename="document"'); done(); }); }) }) describe('.download(path, fn)', function(){ it('should invoke the callback', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.download('test/fixtures/user.html', done); }); request(app) .get('/') .end(function(err, res){ res.should.have.header('Content-Type', 'text/html; charset=UTF-8'); res.should.have.header('Content-Disposition', 'attachment; filename="user.html"'); }); }) }) describe('.download(path, filename, fn)', function(){ it('should invoke the callback', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.download('test/fixtures/user.html', 'document', done); }); request(app) .get('/') .end(function(err, res){ res.should.have.header('Content-Type', 'text/html; charset=UTF-8'); res.should.have.header('Content-Disposition', 'attachment; filename="document"'); }); }) }) describe('on failure', function(){ it('should invoke the callback', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.download('test/fixtures/foobar.html', function(err){ assert(404 == err.status); assert('ENOENT' == err.code); done(); }); }); request(app) .get('/') .end(function(){}); }) it('should remove Content-Disposition', function(done){ var app = express() , calls = 0; app.use(function(req, res){ res.download('test/fixtures/foobar.html', function(err){ res.end('failed'); }); }); request(app) .get('/') .expect('failed') .end(function(err, res){ if (err) return done(err); res.header.should.not.have.property('content-disposition'); done(); }); }) }) }) 4.1.1~dfsg/test/app.param.js0000644000000000000000000000445712327313561014470 0ustar rootroot var express = require('../') , request = require('supertest'); describe('app', function(){ describe('.param(fn)', function(){ it('should map app.param(name, ...) logic', function(done){ var app = express(); app.param(function(name, regexp){ if (Object.prototype.toString.call(regexp) == '[object RegExp]') { // See #1557 return function(req, res, next, val){ var captures; if (captures = regexp.exec(String(val))) { req.params[name] = captures[1]; next(); } else { next('route'); } } } }) app.param(':name', /^([a-zA-Z]+)$/); app.get('/user/:name', function(req, res){ res.send(req.params.name); }); request(app) .get('/user/tj') .end(function(err, res){ res.text.should.equal('tj'); request(app) .get('/user/123') .expect(404, done); }); }) }) describe('.param(names, fn)', function(){ it('should map the array', function(done){ var app = express(); app.param(['id', 'uid'], function(req, res, next, id){ id = Number(id); if (isNaN(id)) return next('route'); req.params.id = id; next(); }); app.get('/post/:id', function(req, res){ var id = req.params.id; id.should.be.a.Number; res.send('' + id); }); app.get('/user/:uid', function(req, res){ var id = req.params.id; id.should.be.a.Number; res.send('' + id); }); request(app) .get('/user/123') .end(function(err, res){ res.text.should.equal('123'); request(app) .get('/post/123') .expect('123', done); }) }) }) describe('.param(name, fn)', function(){ it('should map logic for a single param', function(done){ var app = express(); app.param('id', function(req, res, next, id){ id = Number(id); if (isNaN(id)) return next('route'); req.params.id = id; next(); }); app.get('/user/:id', function(req, res){ var id = req.params.id; id.should.be.a.Number; res.send('' + id); }); request(app) .get('/user/123') .expect('123', done); }) }) }) 4.1.1~dfsg/test/app.head.js0000644000000000000000000000145312327313561014262 0ustar rootroot var express = require('../'); var request = require('supertest'); var assert = require('assert'); describe('HEAD', function(){ it('should default to GET', function(done){ var app = express(); app.get('/tobi', function(req, res){ // send() detects HEAD res.send('tobi'); }); request(app) .head('/tobi') .expect(200, done); }) }) describe('app.head()', function(){ it('should override', function(done){ var app = express() , called; app.head('/tobi', function(req, res){ called = true; res.end(''); }); app.get('/tobi', function(req, res){ assert(0, 'should not call GET'); res.send('tobi'); }); request(app) .head('/tobi') .expect(200, function(){ assert(called); done(); }); }) }) 4.1.1~dfsg/test/req.range.js0000644000000000000000000000141312327313561014460 0ustar rootroot var express = require('../'); function req(ret) { return { get: function(){ return ret } , __proto__: express.request }; } describe('req', function(){ describe('.range(size)', function(){ it('should return parsed ranges', function(){ var ret = [{ start: 0, end: 50 }, { start: 60, end: 100 }]; ret.type = 'bytes'; req('bytes=0-50,60-100').range(120).should.eql(ret); }) it('should cap to the given size', function(){ var ret = [{ start: 0, end: 74 }]; ret.type = 'bytes'; req('bytes=0-100').range(75).should.eql(ret); }) it('should have a .type', function(){ var ret = [{ start: 0, end: Infinity }]; ret.type = 'users'; req('users=0-').range(Infinity).should.eql(ret); }) }) }) 4.1.1~dfsg/test/app.use.js0000644000000000000000000000320612327313561014153 0ustar rootroot var express = require('../') , request = require('supertest'); describe('app', function(){ it('should emit "mount" when mounted', function(done){ var blog = express() , app = express(); blog.on('mount', function(arg){ arg.should.equal(app); done(); }); app.use(blog); }) describe('.use(app)', function(){ it('should mount the app', function(done){ var blog = express() , app = express(); blog.get('/blog', function(req, res){ res.end('blog'); }); app.use(blog); request(app) .get('/blog') .expect('blog', done); }) it('should support mount-points', function(done){ var blog = express() , forum = express() , app = express(); blog.get('/', function(req, res){ res.end('blog'); }); forum.get('/', function(req, res){ res.end('forum'); }); app.use('/blog', blog); app.use('/forum', forum); request(app) .get('/blog') .expect('blog', function(){ request(app) .get('/forum') .expect('forum', done); }); }) it('should set the child\'s .parent', function(){ var blog = express() , app = express(); app.use('/blog', blog); blog.parent.should.equal(app); }) it('should support dynamic routes', function(done){ var blog = express() , app = express(); blog.get('/', function(req, res){ res.end('success'); }); app.use('/post/:article', blog); request(app) .get('/post/once-upon-a-time') .expect('success', done); }) }) }) 4.1.1~dfsg/test/acceptance/0000755000000000000000000000000012327313561014327 5ustar rootroot4.1.1~dfsg/test/acceptance/downloads.js0000644000000000000000000000154412327313561016663 0ustar rootroot var app = require('../../examples/downloads/app') , request = require('supertest'); describe('downloads', function(){ describe('GET /', function(){ it('should have a link to amazing.txt', function(done){ request(app) .get('/') .expect(/href="\/files\/amazing.txt"/, done) }) }) describe('GET /files/amazing.txt', function(){ it('should have a download header', function(done){ request(app) .get('/files/amazing.txt') .end(function(err, res){ res.status.should.equal(200); res.headers.should.have.property('content-disposition', 'attachment; filename="amazing.txt"') done() }) }) }) describe('GET /files/missing.txt', function(){ it('should respond with 404', function(done){ request(app) .get('/files/missing.txt') .expect(404, done) }) }) })4.1.1~dfsg/test/acceptance/resource.js0000644000000000000000000000271412327313561016520 0ustar rootrootvar app = require('../../examples/resource/app') , request = require('supertest'); describe('resource', function(){ describe('GET /', function(){ it('should respond with instructions', function(done){ request(app) .get('/') .expect(/^

Examples:<\/h1>/,done) }) }) describe('GET /users', function(){ it('should respond with all users', function(done){ request(app) .get('/users') .expect(/^\[{"name":"tj"},{"name":"ciaran"},{"name":"aaron"},{"name":"guillermo"},{"name":"simon"},{"name":"tobi"}\]/,done) }) }) describe('GET /users/1', function(){ it('should respond with user 1', function(done){ request(app) .get('/users/1') .expect(/^{"name":"ciaran"}/,done) }) }) describe('GET /users/1..3', function(){ it('should respond with users 1 through 3', function(done){ request(app) .get('/users/1..3') .expect(/^