github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/docs/examples/example-nodejs-fileserver/node_modules/express/lib/request.js (about)

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