github.com/cloudcredo/cloudrocker@v0.0.0-20160108110610-1320f8cc2dfd/sample-apps/node/node_modules/express/lib/utils.js (about)

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