Ein Projekt das es ermöglicht Beerpong über das Internet von zwei unabhängigen positionen aus zu spielen. Entstehung im Rahmen einer Praktikumsaufgabe im Fach Interaktion.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

application.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /**
  2. * Module dependencies.
  3. */
  4. var finalhandler = require('finalhandler');
  5. var flatten = require('./utils').flatten;
  6. var mixin = require('utils-merge');
  7. var Router = require('./router');
  8. var methods = require('methods');
  9. var middleware = require('./middleware/init');
  10. var query = require('./middleware/query');
  11. var debug = require('debug')('express:application');
  12. var View = require('./view');
  13. var http = require('http');
  14. var compileETag = require('./utils').compileETag;
  15. var compileQueryParser = require('./utils').compileQueryParser;
  16. var compileTrust = require('./utils').compileTrust;
  17. var deprecate = require('depd')('express');
  18. var resolve = require('path').resolve;
  19. var slice = Array.prototype.slice;
  20. /**
  21. * Application prototype.
  22. */
  23. var app = exports = module.exports = {};
  24. /**
  25. * Initialize the server.
  26. *
  27. * - setup default configuration
  28. * - setup default middleware
  29. * - setup route reflection methods
  30. *
  31. * @api private
  32. */
  33. app.init = function(){
  34. this.cache = {};
  35. this.settings = {};
  36. this.engines = {};
  37. this.defaultConfiguration();
  38. };
  39. /**
  40. * Initialize application configuration.
  41. *
  42. * @api private
  43. */
  44. app.defaultConfiguration = function(){
  45. // default settings
  46. this.enable('x-powered-by');
  47. this.set('etag', 'weak');
  48. var env = process.env.NODE_ENV || 'development';
  49. this.set('env', env);
  50. this.set('query parser', 'extended');
  51. this.set('subdomain offset', 2);
  52. this.set('trust proxy', false);
  53. debug('booting in %s mode', env);
  54. // inherit protos
  55. this.on('mount', function(parent){
  56. this.request.__proto__ = parent.request;
  57. this.response.__proto__ = parent.response;
  58. this.engines.__proto__ = parent.engines;
  59. this.settings.__proto__ = parent.settings;
  60. });
  61. // setup locals
  62. this.locals = Object.create(null);
  63. // top-most app is mounted at /
  64. this.mountpath = '/';
  65. // default locals
  66. this.locals.settings = this.settings;
  67. // default configuration
  68. this.set('view', View);
  69. this.set('views', resolve('views'));
  70. this.set('jsonp callback name', 'callback');
  71. if (env === 'production') {
  72. this.enable('view cache');
  73. }
  74. Object.defineProperty(this, 'router', {
  75. get: function() {
  76. 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.');
  77. }
  78. });
  79. };
  80. /**
  81. * lazily adds the base router if it has not yet been added.
  82. *
  83. * We cannot add the base router in the defaultConfiguration because
  84. * it reads app settings which might be set after that has run.
  85. *
  86. * @api private
  87. */
  88. app.lazyrouter = function() {
  89. if (!this._router) {
  90. this._router = new Router({
  91. caseSensitive: this.enabled('case sensitive routing'),
  92. strict: this.enabled('strict routing')
  93. });
  94. this._router.use(query(this.get('query parser fn')));
  95. this._router.use(middleware.init(this));
  96. }
  97. };
  98. /**
  99. * Dispatch a req, res pair into the application. Starts pipeline processing.
  100. *
  101. * If no _done_ callback is provided, then default error handlers will respond
  102. * in the event of an error bubbling through the stack.
  103. *
  104. * @api private
  105. */
  106. app.handle = function(req, res, done) {
  107. var router = this._router;
  108. // final handler
  109. done = done || finalhandler(req, res, {
  110. env: this.get('env'),
  111. onerror: logerror.bind(this)
  112. });
  113. // no routes
  114. if (!router) {
  115. debug('no routes defined on app');
  116. done();
  117. return;
  118. }
  119. router.handle(req, res, done);
  120. };
  121. /**
  122. * Proxy `Router#use()` to add middleware to the app router.
  123. * See Router#use() documentation for details.
  124. *
  125. * If the _fn_ parameter is an express app, then it will be
  126. * mounted at the _route_ specified.
  127. *
  128. * @api public
  129. */
  130. app.use = function use(fn) {
  131. var offset = 0;
  132. var path = '/';
  133. var self = this;
  134. // default path to '/'
  135. // disambiguate app.use([fn])
  136. if (typeof fn !== 'function') {
  137. var arg = fn;
  138. while (Array.isArray(arg) && arg.length !== 0) {
  139. arg = arg[0];
  140. }
  141. // first arg is the path
  142. if (typeof arg !== 'function') {
  143. offset = 1;
  144. path = fn;
  145. }
  146. }
  147. var fns = flatten(slice.call(arguments, offset));
  148. if (fns.length === 0) {
  149. throw new TypeError('app.use() requires middleware functions');
  150. }
  151. // setup router
  152. this.lazyrouter();
  153. var router = this._router;
  154. fns.forEach(function (fn) {
  155. // non-express app
  156. if (!fn || !fn.handle || !fn.set) {
  157. return router.use(path, fn);
  158. }
  159. debug('.use app under %s', path);
  160. fn.mountpath = path;
  161. fn.parent = self;
  162. // restore .app property on req and res
  163. router.use(path, function mounted_app(req, res, next) {
  164. var orig = req.app;
  165. fn.handle(req, res, function (err) {
  166. req.__proto__ = orig.request;
  167. res.__proto__ = orig.response;
  168. next(err);
  169. });
  170. });
  171. // mounted an app
  172. fn.emit('mount', self);
  173. });
  174. return this;
  175. };
  176. /**
  177. * Proxy to the app `Router#route()`
  178. * Returns a new `Route` instance for the _path_.
  179. *
  180. * Routes are isolated middleware stacks for specific paths.
  181. * See the Route api docs for details.
  182. *
  183. * @api public
  184. */
  185. app.route = function(path){
  186. this.lazyrouter();
  187. return this._router.route(path);
  188. };
  189. /**
  190. * Register the given template engine callback `fn`
  191. * as `ext`.
  192. *
  193. * By default will `require()` the engine based on the
  194. * file extension. For example if you try to render
  195. * a "foo.jade" file Express will invoke the following internally:
  196. *
  197. * app.engine('jade', require('jade').__express);
  198. *
  199. * For engines that do not provide `.__express` out of the box,
  200. * or if you wish to "map" a different extension to the template engine
  201. * you may use this method. For example mapping the EJS template engine to
  202. * ".html" files:
  203. *
  204. * app.engine('html', require('ejs').renderFile);
  205. *
  206. * In this case EJS provides a `.renderFile()` method with
  207. * the same signature that Express expects: `(path, options, callback)`,
  208. * though note that it aliases this method as `ejs.__express` internally
  209. * so if you're using ".ejs" extensions you dont need to do anything.
  210. *
  211. * Some template engines do not follow this convention, the
  212. * [Consolidate.js](https://github.com/visionmedia/consolidate.js)
  213. * library was created to map all of node's popular template
  214. * engines to follow this convention, thus allowing them to
  215. * work seamlessly within Express.
  216. *
  217. * @param {String} ext
  218. * @param {Function} fn
  219. * @return {app} for chaining
  220. * @api public
  221. */
  222. app.engine = function(ext, fn){
  223. if ('function' != typeof fn) throw new Error('callback function required');
  224. if ('.' != ext[0]) ext = '.' + ext;
  225. this.engines[ext] = fn;
  226. return this;
  227. };
  228. /**
  229. * Proxy to `Router#param()` with one added api feature. The _name_ parameter
  230. * can be an array of names.
  231. *
  232. * See the Router#param() docs for more details.
  233. *
  234. * @param {String|Array} name
  235. * @param {Function} fn
  236. * @return {app} for chaining
  237. * @api public
  238. */
  239. app.param = function(name, fn){
  240. var self = this;
  241. self.lazyrouter();
  242. if (Array.isArray(name)) {
  243. name.forEach(function(key) {
  244. self.param(key, fn);
  245. });
  246. return this;
  247. }
  248. self._router.param(name, fn);
  249. return this;
  250. };
  251. /**
  252. * Assign `setting` to `val`, or return `setting`'s value.
  253. *
  254. * app.set('foo', 'bar');
  255. * app.get('foo');
  256. * // => "bar"
  257. *
  258. * Mounted servers inherit their parent server's settings.
  259. *
  260. * @param {String} setting
  261. * @param {*} [val]
  262. * @return {Server} for chaining
  263. * @api public
  264. */
  265. app.set = function(setting, val){
  266. if (arguments.length === 1) {
  267. // app.get(setting)
  268. return this.settings[setting];
  269. }
  270. // set value
  271. this.settings[setting] = val;
  272. // trigger matched settings
  273. switch (setting) {
  274. case 'etag':
  275. debug('compile etag %s', val);
  276. this.set('etag fn', compileETag(val));
  277. break;
  278. case 'query parser':
  279. debug('compile query parser %s', val);
  280. this.set('query parser fn', compileQueryParser(val));
  281. break;
  282. case 'trust proxy':
  283. debug('compile trust proxy %s', val);
  284. this.set('trust proxy fn', compileTrust(val));
  285. break;
  286. }
  287. return this;
  288. };
  289. /**
  290. * Return the app's absolute pathname
  291. * based on the parent(s) that have
  292. * mounted it.
  293. *
  294. * For example if the application was
  295. * mounted as "/admin", which itself
  296. * was mounted as "/blog" then the
  297. * return value would be "/blog/admin".
  298. *
  299. * @return {String}
  300. * @api private
  301. */
  302. app.path = function(){
  303. return this.parent
  304. ? this.parent.path() + this.mountpath
  305. : '';
  306. };
  307. /**
  308. * Check if `setting` is enabled (truthy).
  309. *
  310. * app.enabled('foo')
  311. * // => false
  312. *
  313. * app.enable('foo')
  314. * app.enabled('foo')
  315. * // => true
  316. *
  317. * @param {String} setting
  318. * @return {Boolean}
  319. * @api public
  320. */
  321. app.enabled = function(setting){
  322. return !!this.set(setting);
  323. };
  324. /**
  325. * Check if `setting` is disabled.
  326. *
  327. * app.disabled('foo')
  328. * // => true
  329. *
  330. * app.enable('foo')
  331. * app.disabled('foo')
  332. * // => false
  333. *
  334. * @param {String} setting
  335. * @return {Boolean}
  336. * @api public
  337. */
  338. app.disabled = function(setting){
  339. return !this.set(setting);
  340. };
  341. /**
  342. * Enable `setting`.
  343. *
  344. * @param {String} setting
  345. * @return {app} for chaining
  346. * @api public
  347. */
  348. app.enable = function(setting){
  349. return this.set(setting, true);
  350. };
  351. /**
  352. * Disable `setting`.
  353. *
  354. * @param {String} setting
  355. * @return {app} for chaining
  356. * @api public
  357. */
  358. app.disable = function(setting){
  359. return this.set(setting, false);
  360. };
  361. /**
  362. * Delegate `.VERB(...)` calls to `router.VERB(...)`.
  363. */
  364. methods.forEach(function(method){
  365. app[method] = function(path){
  366. if ('get' == method && 1 == arguments.length) return this.set(path);
  367. this.lazyrouter();
  368. var route = this._router.route(path);
  369. route[method].apply(route, slice.call(arguments, 1));
  370. return this;
  371. };
  372. });
  373. /**
  374. * Special-cased "all" method, applying the given route `path`,
  375. * middleware, and callback to _every_ HTTP method.
  376. *
  377. * @param {String} path
  378. * @param {Function} ...
  379. * @return {app} for chaining
  380. * @api public
  381. */
  382. app.all = function(path){
  383. this.lazyrouter();
  384. var route = this._router.route(path);
  385. var args = slice.call(arguments, 1);
  386. methods.forEach(function(method){
  387. route[method].apply(route, args);
  388. });
  389. return this;
  390. };
  391. // del -> delete alias
  392. app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead');
  393. /**
  394. * Render the given view `name` name with `options`
  395. * and a callback accepting an error and the
  396. * rendered template string.
  397. *
  398. * Example:
  399. *
  400. * app.render('email', { name: 'Tobi' }, function(err, html){
  401. * // ...
  402. * })
  403. *
  404. * @param {String} name
  405. * @param {String|Function} options or fn
  406. * @param {Function} fn
  407. * @api public
  408. */
  409. app.render = function(name, options, fn){
  410. var opts = {};
  411. var cache = this.cache;
  412. var engines = this.engines;
  413. var view;
  414. // support callback function as second arg
  415. if ('function' == typeof options) {
  416. fn = options, options = {};
  417. }
  418. // merge app.locals
  419. mixin(opts, this.locals);
  420. // merge options._locals
  421. if (options._locals) mixin(opts, options._locals);
  422. // merge options
  423. mixin(opts, options);
  424. // set .cache unless explicitly provided
  425. opts.cache = null == opts.cache
  426. ? this.enabled('view cache')
  427. : opts.cache;
  428. // primed cache
  429. if (opts.cache) view = cache[name];
  430. // view
  431. if (!view) {
  432. view = new (this.get('view'))(name, {
  433. defaultEngine: this.get('view engine'),
  434. root: this.get('views'),
  435. engines: engines
  436. });
  437. if (!view.path) {
  438. var err = new Error('Failed to lookup view "' + name + '" in views directory "' + view.root + '"');
  439. err.view = view;
  440. return fn(err);
  441. }
  442. // prime the cache
  443. if (opts.cache) cache[name] = view;
  444. }
  445. // render
  446. try {
  447. view.render(opts, fn);
  448. } catch (err) {
  449. fn(err);
  450. }
  451. };
  452. /**
  453. * Listen for connections.
  454. *
  455. * A node `http.Server` is returned, with this
  456. * application (which is a `Function`) as its
  457. * callback. If you wish to create both an HTTP
  458. * and HTTPS server you may do so with the "http"
  459. * and "https" modules as shown here:
  460. *
  461. * var http = require('http')
  462. * , https = require('https')
  463. * , express = require('express')
  464. * , app = express();
  465. *
  466. * http.createServer(app).listen(80);
  467. * https.createServer({ ... }, app).listen(443);
  468. *
  469. * @return {http.Server}
  470. * @api public
  471. */
  472. app.listen = function(){
  473. var server = http.createServer(this);
  474. return server.listen.apply(server, arguments);
  475. };
  476. /**
  477. * Log error using console.error.
  478. *
  479. * @param {Error} err
  480. * @api public
  481. */
  482. function logerror(err){
  483. if (this.get('env') !== 'test') console.error(err.stack || err.toString());
  484. }