annotate node_modules/express/lib/utils.js @ 101:52e44ee1c791 tip master

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