The LM Control website. Simple yet efficient.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

utils.js 5.8KB

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