| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 | /*! * express * Copyright(c) 2009-2013 TJ Holowaychuk * Copyright(c) 2014-2015 Douglas Christopher Wilson * MIT Licensed */'use strict';/** * Module dependencies. * @api private */var Buffer = require('safe-buffer').Buffervar contentDisposition = require('content-disposition');var contentType = require('content-type');var deprecate = require('depd')('express');var flatten = require('array-flatten');var mime = require('send').mime;var etag = require('etag');var proxyaddr = require('proxy-addr');var qs = require('qs');var querystring = require('querystring');/** * Return strong ETag for `body`. * * @param {String|Buffer} body * @param {String} [encoding] * @return {String} * @api private */exports.etag = createETagGenerator({ weak: false })/** * Return weak ETag for `body`. * * @param {String|Buffer} body * @param {String} [encoding] * @return {String} * @api private */exports.wetag = createETagGenerator({ weak: true })/** * Check if `path` looks absolute. * * @param {String} path * @return {Boolean} * @api private */exports.isAbsolute = function(path){  if ('/' === path[0]) return true;  if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path  if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path};/** * Flatten the given `arr`. * * @param {Array} arr * @return {Array} * @api private */exports.flatten = deprecate.function(flatten,  'utils.flatten: use array-flatten npm module instead');/** * Normalize the given `type`, for example "html" becomes "text/html". * * @param {String} type * @return {Object} * @api private */exports.normalizeType = function(type){  return ~type.indexOf('/')    ? acceptParams(type)    : { value: mime.lookup(type), params: {} };};/** * Normalize `types`, for example "html" becomes "text/html". * * @param {Array} types * @return {Array} * @api private */exports.normalizeTypes = function(types){  var ret = [];  for (var i = 0; i < types.length; ++i) {    ret.push(exports.normalizeType(types[i]));  }  return ret;};/** * Generate Content-Disposition header appropriate for the filename. * non-ascii filenames are urlencoded and a filename* parameter is added * * @param {String} filename * @return {String} * @api private */exports.contentDisposition = deprecate.function(contentDisposition,  'utils.contentDisposition: use content-disposition npm module instead');/** * Parse accept params `str` returning an * object with `.value`, `.quality` and `.params`. * also includes `.originalIndex` for stable sorting * * @param {String} str * @return {Object} * @api private */function acceptParams(str, index) {  var parts = str.split(/ *; */);  var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };  for (var i = 1; i < parts.length; ++i) {    var pms = parts[i].split(/ *= */);    if ('q' === pms[0]) {      ret.quality = parseFloat(pms[1]);    } else {      ret.params[pms[0]] = pms[1];    }  }  return ret;}/** * Compile "etag" value to function. * * @param  {Boolean|String|Function} val * @return {Function} * @api private */exports.compileETag = function(val) {  var fn;  if (typeof val === 'function') {    return val;  }  switch (val) {    case true:    case 'weak':      fn = exports.wetag;      break;    case false:      break;    case 'strong':      fn = exports.etag;      break;    default:      throw new TypeError('unknown value for etag function: ' + val);  }  return fn;}/** * Compile "query parser" value to function. * * @param  {String|Function} val * @return {Function} * @api private */exports.compileQueryParser = function compileQueryParser(val) {  var fn;  if (typeof val === 'function') {    return val;  }  switch (val) {    case true:    case 'simple':      fn = querystring.parse;      break;    case false:      fn = newObject;      break;    case 'extended':      fn = parseExtendedQueryString;      break;    default:      throw new TypeError('unknown value for query parser function: ' + val);  }  return fn;}/** * Compile "proxy trust" value to function. * * @param  {Boolean|String|Number|Array|Function} val * @return {Function} * @api private */exports.compileTrust = function(val) {  if (typeof val === 'function') return val;  if (val === true) {    // Support plain true/false    return function(){ return true };  }  if (typeof val === 'number') {    // Support trusting hop count    return function(a, i){ return i < val };  }  if (typeof val === 'string') {    // Support comma-separated values    val = val.split(/ *, */);  }  return proxyaddr.compile(val || []);}/** * Set the charset in a given Content-Type string. * * @param {String} type * @param {String} charset * @return {String} * @api private */exports.setCharset = function setCharset(type, charset) {  if (!type || !charset) {    return type;  }  // parse type  var parsed = contentType.parse(type);  // set charset  parsed.parameters.charset = charset;  // format type  return contentType.format(parsed);};/** * Create an ETag generator function, generating ETags with * the given options. * * @param {object} options * @return {function} * @private */function createETagGenerator (options) {  return function generateETag (body, encoding) {    var buf = !Buffer.isBuffer(body)      ? Buffer.from(body, encoding)      : body    return etag(buf, options)  }}/** * Parse an extended query string with qs. * * @return {Object} * @private */function parseExtendedQueryString(str) {  return qs.parse(str, {    allowPrototypes: true  });}/** * Return new empty object. * * @return {Object} * @api private */function newObject() {  return {};}
 |