Unverified Commit 9ae60eb6 authored by Mark Stenglein's avatar Mark Stenglein
Browse files

Added initial [express.js](www.expressjs.com) application

parent be7303ac
This diff is collapsed.
(The MIT License)
Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>
Copyright (c) 2013-2014 Roman Shtylman <shtylman+expressjs@gmail.com>
Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>
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.
[![Express Logo](https://i.cloudup.com/zfY6lL7eFa-3000x3000.png)](http://expressjs.com/)
Fast, unopinionated, minimalist web framework for [node](http://nodejs.org).
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Linux Build][travis-image]][travis-url]
[![Windows Build][appveyor-image]][appveyor-url]
[![Test Coverage][coveralls-image]][coveralls-url]
```js
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World')
})
app.listen(3000)
```
## Installation
```bash
$ npm install express
```
## Features
* Robust routing
* Focus on high performance
* Super-high test coverage
* HTTP helpers (redirection, caching, etc)
* View system supporting 14+ template engines
* Content negotiation
* Executable for generating applications quickly
## Docs & Community
* [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/strongloop/expressjs.com)]
* [#express](https://webchat.freenode.net/?channels=express) on freenode IRC
* [Github Organization](https://github.com/expressjs) for Official Middleware & Modules
* Visit the [Wiki](https://github.com/expressjs/express/wiki)
* [Google Group](https://groups.google.com/group/express-js) for discussion
* [Gitter](https://gitter.im/expressjs/express) for support and discussion
* [Русскоязычная документация](http://jsman.ru/express/)
**PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x).
###Security Issues
If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md).
## Quick Start
The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below:
Install the executable. The executable's major version will match Express's:
```bash
$ npm install -g express-generator@4
```
Create the app:
```bash
$ express /tmp/foo && cd /tmp/foo
```
Install dependencies:
```bash
$ npm install
```
Start the server:
```bash
$ npm start
```
## 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](https://github.com/tj/consolidate.js),
you can quickly craft your perfect framework.
## Examples
To view the examples, clone the Express repo and install the dependencies:
```bash
$ git clone git://github.com/expressjs/express.git --depth 1
$ cd express
$ npm install
```
Then run whichever example you want:
```bash
$ node examples/content-negotiation
```
## Tests
To run the test suite, first install the dependencies, then run `npm test`:
```bash
$ npm install
$ npm test
```
## People
The original author of Express is [TJ Holowaychuk](https://github.com/tj) [![TJ's Gratipay][gratipay-image-visionmedia]][gratipay-url-visionmedia]
The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) [![Doug's Gratipay][gratipay-image-dougwilson]][gratipay-url-dougwilson]
[List of all contributors](https://github.com/expressjs/express/graphs/contributors)
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/express.svg
[npm-url]: https://npmjs.org/package/express
[downloads-image]: https://img.shields.io/npm/dm/express.svg
[downloads-url]: https://npmjs.org/package/express
[travis-image]: https://img.shields.io/travis/expressjs/express/master.svg?label=linux
[travis-url]: https://travis-ci.org/expressjs/express
[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/express/master.svg?label=windows
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/express
[coveralls-image]: https://img.shields.io/coveralls/expressjs/express/master.svg
[coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master
[gratipay-image-visionmedia]: https://img.shields.io/gratipay/visionmedia.svg
[gratipay-url-visionmedia]: https://gratipay.com/visionmedia/
[gratipay-image-dougwilson]: https://img.shields.io/gratipay/dougwilson.svg
[gratipay-url-dougwilson]: https://gratipay.com/dougwilson/
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
module.exports = require('./lib/express');
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict';
/**
* Module dependencies.
* @private
*/
var finalhandler = require('finalhandler');
var Router = require('./router');
var methods = require('methods');
var middleware = require('./middleware/init');
var query = require('./middleware/query');
var debug = require('debug')('express:application');
var View = require('./view');
var http = require('http');
var compileETag = require('./utils').compileETag;
var compileQueryParser = require('./utils').compileQueryParser;
var compileTrust = require('./utils').compileTrust;
var deprecate = require('depd')('express');
var flatten = require('array-flatten');
var merge = require('utils-merge');
var resolve = require('path').resolve;
var slice = Array.prototype.slice;
/**
* Application prototype.
*/
var app = exports = module.exports = {};
/**
* Variable for trust proxy inheritance back-compat
* @private
*/
var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';
/**
* Initialize the server.
*
* - setup default configuration
* - setup default middleware
* - setup route reflection methods
*
* @private
*/
app.init = function init() {
this.cache = {};
this.engines = {};
this.settings = {};
this.defaultConfiguration();
};
/**
* Initialize application configuration.
* @private
*/
app.defaultConfiguration = function defaultConfiguration() {
var env = process.env.NODE_ENV || 'development';
// default settings
this.enable('x-powered-by');
this.set('etag', 'weak');
this.set('env', env);
this.set('query parser', 'extended');
this.set('subdomain offset', 2);
this.set('trust proxy', false);
// trust proxy inherit back-compat
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
configurable: true,
value: true
});
debug('booting in %s mode', env);
this.on('mount', function onmount(parent) {
// inherit trust proxy
if (this.settings[trustProxyDefaultSymbol] === true
&& typeof parent.settings['trust proxy fn'] === 'function') {
delete this.settings['trust proxy'];
delete this.settings['trust proxy fn'];
}
// inherit protos
this.request.__proto__ = parent.request;
this.response.__proto__ = parent.response;
this.engines.__proto__ = parent.engines;
this.settings.__proto__ = parent.settings;
});
// setup locals
this.locals = Object.create(null);
// top-most app is mounted at /
this.mountpath = '/';
// default locals
this.locals.settings = this.settings;
// default configuration
this.set('view', View);
this.set('views', resolve('views'));
this.set('jsonp callback name', 'callback');
if (env === 'production') {
this.enable('view cache');
}
Object.defineProperty(this, 'router', {
get: function() {
throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.');
}
});
};
/**
* lazily adds the base router if it has not yet been added.
*
* We cannot add the base router in the defaultConfiguration because
* it reads app settings which might be set after that has run.
*
* @private
*/
app.lazyrouter = function lazyrouter() {
if (!this._router) {
this._router = new Router({
caseSensitive: this.enabled('case sensitive routing'),
strict: this.enabled('strict routing')
});
this._router.use(query(this.get('query parser fn')));
this._router.use(middleware.init(this));
}
};
/**
* Dispatch a req, res pair into the application. Starts pipeline processing.
*
* If no callback is provided, then default error handlers will respond
* in the event of an error bubbling through the stack.
*
* @private
*/
app.handle = function handle(req, res, callback) {
var router = this._router;
// final handler
var done = callback || finalhandler(req, res, {
env: this.get('env'),
onerror: logerror.bind(this)
});
// no routes
if (!router) {
debug('no routes defined on app');
done();
return;
}
router.handle(req, res, done);
};
/**
* Proxy `Router#use()` to add middleware to the app router.
* See Router#use() documentation for details.
*
* If the _fn_ parameter is an express app, then it will be
* mounted at the _route_ specified.
*
* @public
*/
app.use = function use(fn) {
var offset = 0;
var path = '/';
// default path to '/'
// disambiguate app.use([fn])
if (typeof fn !== 'function') {
var arg = fn;
while (Array.isArray(arg) && arg.length !== 0) {
arg = arg[0];
}
// first arg is the path
if (typeof arg !== 'function') {
offset = 1;
path = fn;
}
}
var fns = flatten(slice.call(arguments, offset));
if (fns.length === 0) {
throw new TypeError('app.use() requires middleware functions');
}
// setup router
this.lazyrouter();
var router = this._router;
fns.forEach(function (fn) {
// non-express app
if (!fn || !fn.handle || !fn.set) {
return router.use(path, fn);
}
debug('.use app under %s', path);
fn.mountpath = path;
fn.parent = this;
// restore .app property on req and res
router.use(path, function mounted_app(req, res, next) {
var orig = req.app;
fn.handle(req, res, function (err) {
req.__proto__ = orig.request;
res.__proto__ = orig.response;
next(err);
});
});
// mounted an app
fn.emit('mount', this);
}, this);
return this;
};
/**
* Proxy to the app `Router#route()`
* Returns a new `Route` instance for the _path_.
*
* Routes are isolated middleware stacks for specific paths.
* See the Route api docs for details.
*
* @public
*/
app.route = function route(path) {
this.lazyrouter();
return this._router.route(path);
};
/**
* Register the given template engine callback `fn`
* as `ext`.
*
* By default will `require()` the engine based on the
* file extension. For example if you try to render
* a "foo.jade" file Express will invoke the following internally:
*
* app.engine('jade', require('jade').__express);
*
* For engines that do not provide `.__express` out of the box,
* or if you wish to "map" a different extension to the template engine
* you may use this method. For example mapping the EJS template engine to
* ".html" files:
*
* app.engine('html', require('ejs').renderFile);
*
* In this case EJS provides a `.renderFile()` method with
* the same signature that Express expects: `(path, options, callback)`,
* though note that it aliases this method as `ejs.__express` internally
* so if you're using ".ejs" extensions you dont need to do anything.
*
* Some template engines do not follow this convention, the
* [Consolidate.js](https://github.com/tj/consolidate.js)
* library was created to map all of node's popular template
* engines to follow this convention, thus allowing them to
* work seamlessly within Express.
*
* @param {String} ext
* @param {Function} fn
* @return {app} for chaining
* @public
*/
app.engine = function engine(ext, fn) {
if (typeof fn !== 'function') {
throw new Error('callback function required');
}
// get file extension
var extension = ext[0] !== '.'
? '.' + ext
: ext;
// store engine
this.engines[extension] = 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
* @public
*/
app.param = function param(name, fn) {
this.lazyrouter();
if (Array.isArray(name)) {
for (var i = 0; i < name.length; i++) {
this.param(name[i], fn);
}
return this;
}
this._router.param(name, fn);
return this;
};
/**
* Assign `setting` to `val`, or return `setting`'s value.
*
* app.set('foo', 'bar');
* app.get('foo');
* // => "bar"
*
* Mounted servers inherit their parent server's settings.
*
* @param {String} setting
* @param {*} [val]
* @return {Server} for chaining
* @public
*/
app.set = function set(setting, val) {
if (arguments.length === 1) {
// app.get(setting)
return this.settings[setting];
}
debug('set "%s" to %o', setting, val);
// set value
this.settings[setting] = val;
// trigger matched settings
switch (setting) {
case 'etag':
this.set('etag fn', compileETag(val));
break;
case 'query parser':
this.set('query parser fn', compileQueryParser(val));
break;
case 'trust proxy':
this.set('trust proxy fn', compileTrust(val));
// trust proxy inherit back-compat
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
configurable: true,
value: false
});
break;
}
return this;
};
/**
* Return the app's absolute pathname
* based on the parent(s) that have
* mounted it.
*
* For example if the application was
* mounted as "/admin", which itself
* was mounted as "/blog" then the
* return value would be "/blog/admin".
*
* @return {String}
* @private
*/
app.path = function path() {
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}
* @public
*/
app.enabled = function enabled(setting) {
return Boolean(this.set(setting));
};
/**
* Check if `setting` is disabled.
*
* app.disabled('foo')
* // => true
*