diff options
Diffstat (limited to 'node_modules/express/lib/utils.js')
| -rw-r--r-- | node_modules/express/lib/utils.js | 313 | 
1 files changed, 313 insertions, 0 deletions
| diff --git a/node_modules/express/lib/utils.js b/node_modules/express/lib/utils.js new file mode 100644 index 0000000..fd245a8 --- /dev/null +++ b/node_modules/express/lib/utils.js @@ -0,0 +1,313 @@ + +/** + * Module dependencies. + */ + +var mime = require('connect').mime +  , crc32 = require('buffer-crc32'); + +/** + * toString ref. + */ + +var toString = {}.toString; + +/** + * Return ETag for `body`. + * + * @param {String|Buffer} body + * @return {String} + * @api private + */ + +exports.etag = function(body){ +  return '"' + crc32.signed(body) + '"'; +}; + +/** + * Make `locals()` bound to the given `obj`. + * + * This is used for `app.locals` and `res.locals`. + * + * @param {Object} obj + * @return {Function} + * @api private + */ + +exports.locals = function(obj){ +  function locals(obj){ +    for (var key in obj) locals[key] = obj[key]; +    return obj; +  }; + +  return locals; +}; + +/** + * 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]) return true; +}; + +/** + * Flatten the given `arr`. + * + * @param {Array} arr + * @return {Array} + * @api private + */ + +exports.flatten = function(arr, ret){ +  var ret = ret || [] +    , len = arr.length; +  for (var i = 0; i < len; ++i) { +    if (Array.isArray(arr[i])) { +      exports.flatten(arr[i], ret); +    } else { +      ret.push(arr[i]); +    } +  } +  return ret; +}; + +/** + * 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; +}; + +/** + * Return the acceptable type in `types`, if any. + * + * @param {Array} types + * @param {String} str + * @return {String} + * @api private + */ + +exports.acceptsArray = function(types, str){ +  // accept anything when Accept is not present +  if (!str) return types[0]; + +  // parse +  var accepted = exports.parseAccept(str) +    , normalized = exports.normalizeTypes(types) +    , len = accepted.length; + +  for (var i = 0; i < len; ++i) { +    for (var j = 0, jlen = types.length; j < jlen; ++j) { +      if (exports.accept(normalized[j], accepted[i])) { +        return types[j]; +      } +    } +  } +}; + +/** + * Check if `type(s)` are acceptable based on + * the given `str`. + * + * @param {String|Array} type(s) + * @param {String} str + * @return {Boolean|String} + * @api private + */ + +exports.accepts = function(type, str){ +  if ('string' == typeof type) type = type.split(/ *, */); +  return exports.acceptsArray(type, str); +}; + +/** + * Check if `type` array is acceptable for `other`. + * + * @param {Object} type + * @param {Object} other + * @return {Boolean} + * @api private + */ + +exports.accept = function(type, other){ +  var t = type.value.split('/'); +  return (t[0] == other.type || '*' == other.type) +    && (t[1] == other.subtype || '*' == other.subtype) +    && paramsEqual(type.params, other.params); +}; + +/** + * Check if accept params are equal. + * + * @param {Object} a + * @param {Object} b + * @return {Boolean} + * @api private + */ + +function paramsEqual(a, b){ +  return !Object.keys(a).some(function(k) { +    return a[k] != b[k]; +  }); +} + +/** + * Parse accept `str`, returning + * an array objects containing + * `.type` and `.subtype` along + * with the values provided by + * `parseQuality()`. + * + * @param {Type} name + * @return {Type} + * @api private + */ + +exports.parseAccept = function(str){ +  return exports +    .parseParams(str) +    .map(function(obj){ +      var parts = obj.value.split('/'); +      obj.type = parts[0]; +      obj.subtype = parts[1]; +      return obj; +    }); +}; + +/** + * Parse quality `str`, returning an + * array of objects with `.value`, + * `.quality` and optional `.params` + * + * @param {String} str + * @return {Array} + * @api private + */ + +exports.parseParams = function(str){ +  return str +    .split(/ *, */) +    .map(acceptParams) +    .filter(function(obj){ +      return obj.quality; +    }) +    .sort(function(a, b){ +      if (a.quality === b.quality) { +        return a.originalIndex - b.originalIndex; +      } else { +        return b.quality - a.quality; +      } +    }); +}; + +/** + * 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; +} + +/** + * Escape special characters in the given string of html. + * + * @param  {String} html + * @return {String} + * @api private + */ + +exports.escape = function(html) { +  return String(html) +    .replace(/&/g, '&') +    .replace(/"/g, '"') +    .replace(/</g, '<') +    .replace(/>/g, '>'); +}; + +/** + * Normalize the given path string, + * returning a regular expression. + * + * An empty array should be passed, + * which will contain the placeholder + * key names. For example "/user/:id" will + * then contain ["id"]. + * + * @param  {String|RegExp|Array} path + * @param  {Array} keys + * @param  {Boolean} sensitive + * @param  {Boolean} strict + * @return {RegExp} + * @api private + */ + +exports.pathRegexp = function(path, keys, sensitive, strict) { +  if (toString.call(path) == '[object RegExp]') return path; +  if (Array.isArray(path)) path = '(' + path.join('|') + ')'; +  path = path +    .concat(strict ? '' : '/?') +    .replace(/\/\(/g, '(?:/') +    .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){ +      keys.push({ name: key, optional: !! optional }); +      slash = slash || ''; +      return '' +        + (optional ? '' : slash) +        + '(?:' +        + (optional ? slash : '') +        + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' +        + (optional || '') +        + (star ? '(/*)?' : ''); +    }) +    .replace(/([\/.])/g, '\\$1') +    .replace(/\*/g, '(.*)'); +  return new RegExp('^' + path + '$', sensitive ? '' : 'i'); +} | 
