arnaucube
arnaucube/comunicationLeapPublic Self-hosted repository
comunicationLeap/node_modules/express/lib/utils.js
node_modules/express/lib/utils.jsRaw
  1
  2/**
  3 * Module dependencies.
  4 */
  5
  6var mime = require('connect').mime
  7  , crc32 = require('buffer-crc32');
  8
  9/**
 10 * toString ref.
 11 */
 12
 13var toString = {}.toString;
 14
 15/**
 16 * Return ETag for `body`.
 17 *
 18 * @param {String|Buffer} body
 19 * @return {String}
 20 * @api private
 21 */
 22
 23exports.etag = function(body){
 24  return '"' + crc32.signed(body) + '"';
 25};
 26
 27/**
 28 * Make `locals()` bound to the given `obj`.
 29 *
 30 * This is used for `app.locals` and `res.locals`.
 31 *
 32 * @param {Object} obj
 33 * @return {Function}
 34 * @api private
 35 */
 36
 37exports.locals = function(obj){
 38  function locals(obj){
 39    for (var key in obj) locals[key] = obj[key];
 40    return obj;
 41  };
 42
 43  return locals;
 44};
 45
 46/**
 47 * Check if `path` looks absolute.
 48 *
 49 * @param {String} path
 50 * @return {Boolean}
 51 * @api private
 52 */
 53
 54exports.isAbsolute = function(path){
 55  if ('/' == path[0]) return true;
 56  if (':' == path[1] && '\\' == path[2]) return true;
 57};
 58
 59/**
 60 * Flatten the given `arr`.
 61 *
 62 * @param {Array} arr
 63 * @return {Array}
 64 * @api private
 65 */
 66
 67exports.flatten = function(arr, ret){
 68  var ret = ret || []
 69    , len = arr.length;
 70  for (var i = 0; i < len; ++i) {
 71    if (Array.isArray(arr[i])) {
 72      exports.flatten(arr[i], ret);
 73    } else {
 74      ret.push(arr[i]);
 75    }
 76  }
 77  return ret;
 78};
 79
 80/**
 81 * Normalize the given `type`, for example "html" becomes "text/html".
 82 *
 83 * @param {String} type
 84 * @return {Object}
 85 * @api private
 86 */
 87
 88exports.normalizeType = function(type){
 89  return ~type.indexOf('/')
 90    ? acceptParams(type)
 91    : { value: mime.lookup(type), params: {} };
 92};
 93
 94/**
 95 * Normalize `types`, for example "html" becomes "text/html".
 96 *
 97 * @param {Array} types
 98 * @return {Array}
 99 * @api private
100 */
101
102exports.normalizeTypes = function(types){
103  var ret = [];
104
105  for (var i = 0; i < types.length; ++i) {
106    ret.push(exports.normalizeType(types[i]));
107  }
108
109  return ret;
110};
111
112/**
113 * Return the acceptable type in `types`, if any.
114 *
115 * @param {Array} types
116 * @param {String} str
117 * @return {String}
118 * @api private
119 */
120
121exports.acceptsArray = function(types, str){
122  // accept anything when Accept is not present
123  if (!str) return types[0];
124
125  // parse
126  var accepted = exports.parseAccept(str)
127    , normalized = exports.normalizeTypes(types)
128    , len = accepted.length;
129
130  for (var i = 0; i < len; ++i) {
131    for (var j = 0, jlen = types.length; j < jlen; ++j) {
132      if (exports.accept(normalized[j], accepted[i])) {
133        return types[j];
134      }
135    }
136  }
137};
138
139/**
140 * Check if `type(s)` are acceptable based on
141 * the given `str`.
142 *
143 * @param {String|Array} type(s)
144 * @param {String} str
145 * @return {Boolean|String}
146 * @api private
147 */
148
149exports.accepts = function(type, str){
150  if ('string' == typeof type) type = type.split(/ *, */);
151  return exports.acceptsArray(type, str);
152};
153
154/**
155 * Check if `type` array is acceptable for `other`.
156 *
157 * @param {Object} type
158 * @param {Object} other
159 * @return {Boolean}
160 * @api private
161 */
162
163exports.accept = function(type, other){
164  var t = type.value.split('/');
165  return (t[0] == other.type || '*' == other.type)
166    && (t[1] == other.subtype || '*' == other.subtype)
167    && paramsEqual(type.params, other.params);
168};
169
170/**
171 * Check if accept params are equal.
172 *
173 * @param {Object} a
174 * @param {Object} b
175 * @return {Boolean}
176 * @api private
177 */
178
179function paramsEqual(a, b){
180  return !Object.keys(a).some(function(k) {
181    return a[k] != b[k];
182  });
183}
184
185/**
186 * Parse accept `str`, returning
187 * an array objects containing
188 * `.type` and `.subtype` along
189 * with the values provided by
190 * `parseQuality()`.
191 *
192 * @param {Type} name
193 * @return {Type}
194 * @api private
195 */
196
197exports.parseAccept = function(str){
198  return exports
199    .parseParams(str)
200    .map(function(obj){
201      var parts = obj.value.split('/');
202      obj.type = parts[0];
203      obj.subtype = parts[1];
204      return obj;
205    });
206};
207
208/**
209 * Parse quality `str`, returning an
210 * array of objects with `.value`,
211 * `.quality` and optional `.params`
212 *
213 * @param {String} str
214 * @return {Array}
215 * @api private
216 */
217
218exports.parseParams = function(str){
219  return str
220    .split(/ *, */)
221    .map(acceptParams)
222    .filter(function(obj){
223      return obj.quality;
224    })
225    .sort(function(a, b){
226      if (a.quality === b.quality) {
227        return a.originalIndex - b.originalIndex;
228      } else {
229        return b.quality - a.quality;
230      }
231    });
232};
233
234/**
235 * Parse accept params `str` returning an
236 * object with `.value`, `.quality` and `.params`.
237 * also includes `.originalIndex` for stable sorting
238 *
239 * @param {String} str
240 * @return {Object}
241 * @api private
242 */
243
244function acceptParams(str, index) {
245  var parts = str.split(/ *; */);
246  var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
247
248  for (var i = 1; i < parts.length; ++i) {
249    var pms = parts[i].split(/ *= */);
250    if ('q' == pms[0]) {
251      ret.quality = parseFloat(pms[1]);
252    } else {
253      ret.params[pms[0]] = pms[1];
254    }
255  }
256
257  return ret;
258}
259
260/**
261 * Escape special characters in the given string of html.
262 *
263 * @param  {String} html
264 * @return {String}
265 * @api private
266 */
267
268exports.escape = function(html) {
269  return String(html)
270    .replace(/&/g, '&amp;')
271    .replace(/"/g, '&quot;')
272    .replace(/</g, '&lt;')
273    .replace(/>/g, '&gt;');
274};
275
276/**
277 * Normalize the given path string,
278 * returning a regular expression.
279 *
280 * An empty array should be passed,
281 * which will contain the placeholder
282 * key names. For example "/user/:id" will
283 * then contain ["id"].
284 *
285 * @param  {String|RegExp|Array} path
286 * @param  {Array} keys
287 * @param  {Boolean} sensitive
288 * @param  {Boolean} strict
289 * @return {RegExp}
290 * @api private
291 */
292
293exports.pathRegexp = function(path, keys, sensitive, strict) {
294  if (toString.call(path) == '[object RegExp]') return path;
295  if (Array.isArray(path)) path = '(' + path.join('|') + ')';
296  path = path
297    .concat(strict ? '' : '/?')
298    .replace(/\/\(/g, '(?:/')
299    .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function(_, slash, format, key, capture, optional, star){
300      keys.push({ name: key, optional: !! optional });
301      slash = slash || '';
302      return ''
303        + (optional ? '' : slash)
304        + '(?:'
305        + (optional ? slash : '')
306        + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
307        + (optional || '')
308        + (star ? '(/*)?' : '');
309    })
310    .replace(/([\/.])/g, '\\$1')
311    .replace(/\*/g, '(.*)');
312  return new RegExp('^' + path + '$', sensitive ? '' : 'i');
313}