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.

request.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /**
  2. * Module dependencies.
  3. */
  4. var accepts = require('accepts');
  5. var deprecate = require('depd')('express');
  6. var isIP = require('net').isIP;
  7. var typeis = require('type-is');
  8. var http = require('http');
  9. var fresh = require('fresh');
  10. var parseRange = require('range-parser');
  11. var parse = require('parseurl');
  12. var proxyaddr = require('proxy-addr');
  13. /**
  14. * Request prototype.
  15. */
  16. var req = exports = module.exports = {
  17. __proto__: http.IncomingMessage.prototype
  18. };
  19. /**
  20. * Return request header.
  21. *
  22. * The `Referrer` header field is special-cased,
  23. * both `Referrer` and `Referer` are interchangeable.
  24. *
  25. * Examples:
  26. *
  27. * req.get('Content-Type');
  28. * // => "text/plain"
  29. *
  30. * req.get('content-type');
  31. * // => "text/plain"
  32. *
  33. * req.get('Something');
  34. * // => undefined
  35. *
  36. * Aliased as `req.header()`.
  37. *
  38. * @param {String} name
  39. * @return {String}
  40. * @api public
  41. */
  42. req.get =
  43. req.header = function(name){
  44. switch (name = name.toLowerCase()) {
  45. case 'referer':
  46. case 'referrer':
  47. return this.headers.referrer
  48. || this.headers.referer;
  49. default:
  50. return this.headers[name];
  51. }
  52. };
  53. /**
  54. * To do: update docs.
  55. *
  56. * Check if the given `type(s)` is acceptable, returning
  57. * the best match when true, otherwise `undefined`, in which
  58. * case you should respond with 406 "Not Acceptable".
  59. *
  60. * The `type` value may be a single mime type string
  61. * such as "application/json", the extension name
  62. * such as "json", a comma-delimted list such as "json, html, text/plain",
  63. * an argument list such as `"json", "html", "text/plain"`,
  64. * or an array `["json", "html", "text/plain"]`. When a list
  65. * or array is given the _best_ match, if any is returned.
  66. *
  67. * Examples:
  68. *
  69. * // Accept: text/html
  70. * req.accepts('html');
  71. * // => "html"
  72. *
  73. * // Accept: text/*, application/json
  74. * req.accepts('html');
  75. * // => "html"
  76. * req.accepts('text/html');
  77. * // => "text/html"
  78. * req.accepts('json, text');
  79. * // => "json"
  80. * req.accepts('application/json');
  81. * // => "application/json"
  82. *
  83. * // Accept: text/*, application/json
  84. * req.accepts('image/png');
  85. * req.accepts('png');
  86. * // => undefined
  87. *
  88. * // Accept: text/*;q=.5, application/json
  89. * req.accepts(['html', 'json']);
  90. * req.accepts('html', 'json');
  91. * req.accepts('html, json');
  92. * // => "json"
  93. *
  94. * @param {String|Array} type(s)
  95. * @return {String}
  96. * @api public
  97. */
  98. req.accepts = function(){
  99. var accept = accepts(this);
  100. return accept.types.apply(accept, arguments);
  101. };
  102. /**
  103. * Check if the given `encoding`s are accepted.
  104. *
  105. * @param {String} ...encoding
  106. * @return {Boolean}
  107. * @api public
  108. */
  109. req.acceptsEncodings = function(){
  110. var accept = accepts(this);
  111. return accept.encodings.apply(accept, arguments);
  112. };
  113. req.acceptsEncoding = deprecate.function(req.acceptsEncodings,
  114. 'req.acceptsEncoding: Use acceptsEncodings instead');
  115. /**
  116. * Check if the given `charset`s are acceptable,
  117. * otherwise you should respond with 406 "Not Acceptable".
  118. *
  119. * @param {String} ...charset
  120. * @return {Boolean}
  121. * @api public
  122. */
  123. req.acceptsCharsets = function(){
  124. var accept = accepts(this);
  125. return accept.charsets.apply(accept, arguments);
  126. };
  127. req.acceptsCharset = deprecate.function(req.acceptsCharsets,
  128. 'req.acceptsCharset: Use acceptsCharsets instead');
  129. /**
  130. * Check if the given `lang`s are acceptable,
  131. * otherwise you should respond with 406 "Not Acceptable".
  132. *
  133. * @param {String} ...lang
  134. * @return {Boolean}
  135. * @api public
  136. */
  137. req.acceptsLanguages = function(){
  138. var accept = accepts(this);
  139. return accept.languages.apply(accept, arguments);
  140. };
  141. req.acceptsLanguage = deprecate.function(req.acceptsLanguages,
  142. 'req.acceptsLanguage: Use acceptsLanguages instead');
  143. /**
  144. * Parse Range header field,
  145. * capping to the given `size`.
  146. *
  147. * Unspecified ranges such as "0-" require
  148. * knowledge of your resource length. In
  149. * the case of a byte range this is of course
  150. * the total number of bytes. If the Range
  151. * header field is not given `null` is returned,
  152. * `-1` when unsatisfiable, `-2` when syntactically invalid.
  153. *
  154. * NOTE: remember that ranges are inclusive, so
  155. * for example "Range: users=0-3" should respond
  156. * with 4 users when available, not 3.
  157. *
  158. * @param {Number} size
  159. * @return {Array}
  160. * @api public
  161. */
  162. req.range = function(size){
  163. var range = this.get('Range');
  164. if (!range) return;
  165. return parseRange(size, range);
  166. };
  167. /**
  168. * Return the value of param `name` when present or `defaultValue`.
  169. *
  170. * - Checks route placeholders, ex: _/user/:id_
  171. * - Checks body params, ex: id=12, {"id":12}
  172. * - Checks query string params, ex: ?id=12
  173. *
  174. * To utilize request bodies, `req.body`
  175. * should be an object. This can be done by using
  176. * the `bodyParser()` middleware.
  177. *
  178. * @param {String} name
  179. * @param {Mixed} [defaultValue]
  180. * @return {String}
  181. * @api public
  182. */
  183. req.param = function(name, defaultValue){
  184. var params = this.params || {};
  185. var body = this.body || {};
  186. var query = this.query || {};
  187. if (null != params[name] && params.hasOwnProperty(name)) return params[name];
  188. if (null != body[name]) return body[name];
  189. if (null != query[name]) return query[name];
  190. return defaultValue;
  191. };
  192. /**
  193. * Check if the incoming request contains the "Content-Type"
  194. * header field, and it contains the give mime `type`.
  195. *
  196. * Examples:
  197. *
  198. * // With Content-Type: text/html; charset=utf-8
  199. * req.is('html');
  200. * req.is('text/html');
  201. * req.is('text/*');
  202. * // => true
  203. *
  204. * // When Content-Type is application/json
  205. * req.is('json');
  206. * req.is('application/json');
  207. * req.is('application/*');
  208. * // => true
  209. *
  210. * req.is('html');
  211. * // => false
  212. *
  213. * @param {String} type
  214. * @return {Boolean}
  215. * @api public
  216. */
  217. req.is = function(types){
  218. if (!Array.isArray(types)) types = [].slice.call(arguments);
  219. return typeis(this, types);
  220. };
  221. /**
  222. * Return the protocol string "http" or "https"
  223. * when requested with TLS. When the "trust proxy"
  224. * setting trusts the socket address, the
  225. * "X-Forwarded-Proto" header field will be trusted
  226. * and used if present.
  227. *
  228. * If you're running behind a reverse proxy that
  229. * supplies https for you this may be enabled.
  230. *
  231. * @return {String}
  232. * @api public
  233. */
  234. defineGetter(req, 'protocol', function protocol(){
  235. var proto = this.connection.encrypted
  236. ? 'https'
  237. : 'http';
  238. var trust = this.app.get('trust proxy fn');
  239. if (!trust(this.connection.remoteAddress)) {
  240. return proto;
  241. }
  242. // Note: X-Forwarded-Proto is normally only ever a
  243. // single value, but this is to be safe.
  244. proto = this.get('X-Forwarded-Proto') || proto;
  245. return proto.split(/\s*,\s*/)[0];
  246. });
  247. /**
  248. * Short-hand for:
  249. *
  250. * req.protocol == 'https'
  251. *
  252. * @return {Boolean}
  253. * @api public
  254. */
  255. defineGetter(req, 'secure', function secure(){
  256. return 'https' == this.protocol;
  257. });
  258. /**
  259. * Return the remote address from the trusted proxy.
  260. *
  261. * The is the remote address on the socket unless
  262. * "trust proxy" is set.
  263. *
  264. * @return {String}
  265. * @api public
  266. */
  267. defineGetter(req, 'ip', function ip(){
  268. var trust = this.app.get('trust proxy fn');
  269. return proxyaddr(this, trust);
  270. });
  271. /**
  272. * When "trust proxy" is set, trusted proxy addresses + client.
  273. *
  274. * For example if the value were "client, proxy1, proxy2"
  275. * you would receive the array `["client", "proxy1", "proxy2"]`
  276. * where "proxy2" is the furthest down-stream and "proxy1" and
  277. * "proxy2" were trusted.
  278. *
  279. * @return {Array}
  280. * @api public
  281. */
  282. defineGetter(req, 'ips', function ips() {
  283. var trust = this.app.get('trust proxy fn');
  284. var addrs = proxyaddr.all(this, trust);
  285. return addrs.slice(1).reverse();
  286. });
  287. /**
  288. * Return subdomains as an array.
  289. *
  290. * Subdomains are the dot-separated parts of the host before the main domain of
  291. * the app. By default, the domain of the app is assumed to be the last two
  292. * parts of the host. This can be changed by setting "subdomain offset".
  293. *
  294. * For example, if the domain is "tobi.ferrets.example.com":
  295. * If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
  296. * If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
  297. *
  298. * @return {Array}
  299. * @api public
  300. */
  301. defineGetter(req, 'subdomains', function subdomains() {
  302. var hostname = this.hostname;
  303. if (!hostname) return [];
  304. var offset = this.app.get('subdomain offset');
  305. var subdomains = !isIP(hostname)
  306. ? hostname.split('.').reverse()
  307. : [hostname];
  308. return subdomains.slice(offset);
  309. });
  310. /**
  311. * Short-hand for `url.parse(req.url).pathname`.
  312. *
  313. * @return {String}
  314. * @api public
  315. */
  316. defineGetter(req, 'path', function path() {
  317. return parse(this).pathname;
  318. });
  319. /**
  320. * Parse the "Host" header field to a hostname.
  321. *
  322. * When the "trust proxy" setting trusts the socket
  323. * address, the "X-Forwarded-Host" header field will
  324. * be trusted.
  325. *
  326. * @return {String}
  327. * @api public
  328. */
  329. defineGetter(req, 'hostname', function hostname(){
  330. var trust = this.app.get('trust proxy fn');
  331. var host = this.get('X-Forwarded-Host');
  332. if (!host || !trust(this.connection.remoteAddress)) {
  333. host = this.get('Host');
  334. }
  335. if (!host) return;
  336. // IPv6 literal support
  337. var offset = host[0] === '['
  338. ? host.indexOf(']') + 1
  339. : 0;
  340. var index = host.indexOf(':', offset);
  341. return ~index
  342. ? host.substring(0, index)
  343. : host;
  344. });
  345. // TODO: change req.host to return host in next major
  346. defineGetter(req, 'host', deprecate.function(function host(){
  347. return this.hostname;
  348. }, 'req.host: Use req.hostname instead'));
  349. /**
  350. * Check if the request is fresh, aka
  351. * Last-Modified and/or the ETag
  352. * still match.
  353. *
  354. * @return {Boolean}
  355. * @api public
  356. */
  357. defineGetter(req, 'fresh', function(){
  358. var method = this.method;
  359. var s = this.res.statusCode;
  360. // GET or HEAD for weak freshness validation only
  361. if ('GET' != method && 'HEAD' != method) return false;
  362. // 2xx or 304 as per rfc2616 14.26
  363. if ((s >= 200 && s < 300) || 304 == s) {
  364. return fresh(this.headers, this.res._headers);
  365. }
  366. return false;
  367. });
  368. /**
  369. * Check if the request is stale, aka
  370. * "Last-Modified" and / or the "ETag" for the
  371. * resource has changed.
  372. *
  373. * @return {Boolean}
  374. * @api public
  375. */
  376. defineGetter(req, 'stale', function stale(){
  377. return !this.fresh;
  378. });
  379. /**
  380. * Check if the request was an _XMLHttpRequest_.
  381. *
  382. * @return {Boolean}
  383. * @api public
  384. */
  385. defineGetter(req, 'xhr', function xhr(){
  386. var val = this.get('X-Requested-With') || '';
  387. return 'xmlhttprequest' == val.toLowerCase();
  388. });
  389. /**
  390. * Helper function for creating a getter on an object.
  391. *
  392. * @param {Object} obj
  393. * @param {String} name
  394. * @param {Function} getter
  395. * @api private
  396. */
  397. function defineGetter(obj, name, getter) {
  398. Object.defineProperty(obj, name, {
  399. configurable: true,
  400. enumerable: true,
  401. get: getter
  402. });
  403. };