github.com/solo-io/unik@v0.0.0-20190717152701-a58d3e8e33b7/docs/examples/example-nodejs-fileserver/node_modules/express/lib/utils.js (about)

     1  /*!
     2   * express
     3   * Copyright(c) 2009-2013 TJ Holowaychuk
     4   * Copyright(c) 2014-2015 Douglas Christopher Wilson
     5   * MIT Licensed
     6   */
     7  
     8  'use strict';
     9  
    10  /**
    11   * Module dependencies.
    12   * @api private
    13   */
    14  
    15  var contentDisposition = require('content-disposition');
    16  var contentType = require('content-type');
    17  var deprecate = require('depd')('express');
    18  var flatten = require('array-flatten');
    19  var mime = require('send').mime;
    20  var basename = require('path').basename;
    21  var etag = require('etag');
    22  var proxyaddr = require('proxy-addr');
    23  var qs = require('qs');
    24  var querystring = require('querystring');
    25  
    26  /**
    27   * Return strong ETag for `body`.
    28   *
    29   * @param {String|Buffer} body
    30   * @param {String} [encoding]
    31   * @return {String}
    32   * @api private
    33   */
    34  
    35  exports.etag = function (body, encoding) {
    36    var buf = !Buffer.isBuffer(body)
    37      ? new Buffer(body, encoding)
    38      : body;
    39  
    40    return etag(buf, {weak: false});
    41  };
    42  
    43  /**
    44   * Return weak ETag for `body`.
    45   *
    46   * @param {String|Buffer} body
    47   * @param {String} [encoding]
    48   * @return {String}
    49   * @api private
    50   */
    51  
    52  exports.wetag = function wetag(body, encoding){
    53    var buf = !Buffer.isBuffer(body)
    54      ? new Buffer(body, encoding)
    55      : body;
    56  
    57    return etag(buf, {weak: true});
    58  };
    59  
    60  /**
    61   * Check if `path` looks absolute.
    62   *
    63   * @param {String} path
    64   * @return {Boolean}
    65   * @api private
    66   */
    67  
    68  exports.isAbsolute = function(path){
    69    if ('/' == path[0]) return true;
    70    if (':' == path[1] && '\\' == path[2]) return true;
    71    if ('\\\\' == path.substring(0, 2)) return true; // Microsoft Azure absolute path
    72  };
    73  
    74  /**
    75   * Flatten the given `arr`.
    76   *
    77   * @param {Array} arr
    78   * @return {Array}
    79   * @api private
    80   */
    81  
    82  exports.flatten = deprecate.function(flatten,
    83    'utils.flatten: use array-flatten npm module instead');
    84  
    85  /**
    86   * Normalize the given `type`, for example "html" becomes "text/html".
    87   *
    88   * @param {String} type
    89   * @return {Object}
    90   * @api private
    91   */
    92  
    93  exports.normalizeType = function(type){
    94    return ~type.indexOf('/')
    95      ? acceptParams(type)
    96      : { value: mime.lookup(type), params: {} };
    97  };
    98  
    99  /**
   100   * Normalize `types`, for example "html" becomes "text/html".
   101   *
   102   * @param {Array} types
   103   * @return {Array}
   104   * @api private
   105   */
   106  
   107  exports.normalizeTypes = function(types){
   108    var ret = [];
   109  
   110    for (var i = 0; i < types.length; ++i) {
   111      ret.push(exports.normalizeType(types[i]));
   112    }
   113  
   114    return ret;
   115  };
   116  
   117  /**
   118   * Generate Content-Disposition header appropriate for the filename.
   119   * non-ascii filenames are urlencoded and a filename* parameter is added
   120   *
   121   * @param {String} filename
   122   * @return {String}
   123   * @api private
   124   */
   125  
   126  exports.contentDisposition = deprecate.function(contentDisposition,
   127    'utils.contentDisposition: use content-disposition npm module instead');
   128  
   129  /**
   130   * Parse accept params `str` returning an
   131   * object with `.value`, `.quality` and `.params`.
   132   * also includes `.originalIndex` for stable sorting
   133   *
   134   * @param {String} str
   135   * @return {Object}
   136   * @api private
   137   */
   138  
   139  function acceptParams(str, index) {
   140    var parts = str.split(/ *; */);
   141    var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
   142  
   143    for (var i = 1; i < parts.length; ++i) {
   144      var pms = parts[i].split(/ *= */);
   145      if ('q' == pms[0]) {
   146        ret.quality = parseFloat(pms[1]);
   147      } else {
   148        ret.params[pms[0]] = pms[1];
   149      }
   150    }
   151  
   152    return ret;
   153  }
   154  
   155  /**
   156   * Compile "etag" value to function.
   157   *
   158   * @param  {Boolean|String|Function} val
   159   * @return {Function}
   160   * @api private
   161   */
   162  
   163  exports.compileETag = function(val) {
   164    var fn;
   165  
   166    if (typeof val === 'function') {
   167      return val;
   168    }
   169  
   170    switch (val) {
   171      case true:
   172        fn = exports.wetag;
   173        break;
   174      case false:
   175        break;
   176      case 'strong':
   177        fn = exports.etag;
   178        break;
   179      case 'weak':
   180        fn = exports.wetag;
   181        break;
   182      default:
   183        throw new TypeError('unknown value for etag function: ' + val);
   184    }
   185  
   186    return fn;
   187  }
   188  
   189  /**
   190   * Compile "query parser" value to function.
   191   *
   192   * @param  {String|Function} val
   193   * @return {Function}
   194   * @api private
   195   */
   196  
   197  exports.compileQueryParser = function compileQueryParser(val) {
   198    var fn;
   199  
   200    if (typeof val === 'function') {
   201      return val;
   202    }
   203  
   204    switch (val) {
   205      case true:
   206        fn = querystring.parse;
   207        break;
   208      case false:
   209        fn = newObject;
   210        break;
   211      case 'extended':
   212        fn = parseExtendedQueryString;
   213        break;
   214      case 'simple':
   215        fn = querystring.parse;
   216        break;
   217      default:
   218        throw new TypeError('unknown value for query parser function: ' + val);
   219    }
   220  
   221    return fn;
   222  }
   223  
   224  /**
   225   * Compile "proxy trust" value to function.
   226   *
   227   * @param  {Boolean|String|Number|Array|Function} val
   228   * @return {Function}
   229   * @api private
   230   */
   231  
   232  exports.compileTrust = function(val) {
   233    if (typeof val === 'function') return val;
   234  
   235    if (val === true) {
   236      // Support plain true/false
   237      return function(){ return true };
   238    }
   239  
   240    if (typeof val === 'number') {
   241      // Support trusting hop count
   242      return function(a, i){ return i < val };
   243    }
   244  
   245    if (typeof val === 'string') {
   246      // Support comma-separated values
   247      val = val.split(/ *, */);
   248    }
   249  
   250    return proxyaddr.compile(val || []);
   251  }
   252  
   253  /**
   254   * Set the charset in a given Content-Type string.
   255   *
   256   * @param {String} type
   257   * @param {String} charset
   258   * @return {String}
   259   * @api private
   260   */
   261  
   262  exports.setCharset = function setCharset(type, charset) {
   263    if (!type || !charset) {
   264      return type;
   265    }
   266  
   267    // parse type
   268    var parsed = contentType.parse(type);
   269  
   270    // set charset
   271    parsed.parameters.charset = charset;
   272  
   273    // format type
   274    return contentType.format(parsed);
   275  };
   276  
   277  /**
   278   * Parse an extended query string with qs.
   279   *
   280   * @return {Object}
   281   * @private
   282   */
   283  
   284  function parseExtendedQueryString(str) {
   285    return qs.parse(str, {
   286      allowDots: false,
   287      allowPrototypes: true
   288    });
   289  }
   290  
   291  /**
   292   * Return new empty object.
   293   *
   294   * @return {Object}
   295   * @api private
   296   */
   297  
   298  function newObject() {
   299    return {};
   300  }