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