UNPKG

connect

Version:

High performance middleware framework

468 lines (433 loc) 13.1 kB
/*! * Ext JS Connect * Copyright(c) 2010 Sencha Inc. * MIT Licensed */ /** * Module dependencies. */ var queryString = require('querystring') , crypto = require('crypto') , Path = require('path') , fs = require('fs'); /** * Return md5 hash of the given string and optional encoding, * defaulting to hex. * * @param {String} str * @param {String} encoding * @return {String} * @api public */ exports.md5 = function(str, encoding){ return crypto .createHash('md5') .update(str) .digest(encoding || 'hex'); }; /** * Default mime type. */ var defaultMime = exports.defaultMime = 'application/octet-stream'; /** * Converts the given object to a Boolean. * * @param {Mixed} obj * @return {Boolean} * @api public */ exports.toBoolean = function(obj){ return typeof obj === 'string' ? (/^(y(es)?|true|1)$/).test(obj) : !! obj; }; /** * Merge object b with object a. * * @param {Object} a * @param {Object} b * @return {Object} * @api public */ exports.merge = function(a, b){ if (a && b) { var keys = Object.keys(b); for (var i = 0, len = keys.length; i < len; ++i) { a[keys[i]] = b[keys[i]]; } } return a; }; /** * Return a unique identifier with the given `len`. * * @param {Number} len * @return {String} * @api public */ exports.uid = function(len) { var buf = [] , chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' , charlen = chars.length; for (var i = 0; i < len; ++i) { buf.push(chars[getRandomInt(0, charlen - 1)]); } return buf.join(''); }; /** * Parse the given cookie string into an object. * * @param {String} str * @return {Object} * @api public */ exports.parseCookie = function(str){ var obj = {} , pairs = str.split(/[;,] */); for (var i = 0, len = pairs.length; i < len; ++i) { var pair = pairs[i] , eqlIndex = pair.indexOf('=') , key = pair.substr(0, eqlIndex).trim().toLowerCase() , val = pair.substr(++eqlIndex, pair.length).trim(); // Quoted values if (val[0] === '"') { val = val.slice(1, -1); } // Only assign once if (obj[key] === undefined) { obj[key] = queryString.unescape(val, true); } } return obj; }; /** * Serialize the given object into a cookie string. * * @param {String} name * @param {String} val * @param {Object} obj * @return {String} * @api public */ exports.serializeCookie = function(name, val, obj){ var pairs = [name + '=' + queryString.escape(val)] , obj = obj || {} , keys = Object.keys(obj); for (var i = 0, len = keys.length; i < len; ++i) { var key = keys[i] , val = obj[key]; if (val instanceof Date) { val = val.toUTCString(); } else if (typeof val === "boolean") { if (true === val) pairs.push(key); continue; } pairs.push(key + '=' + val); } return pairs.join('; '); }; /** * Pause events on the given `obj`. * * @param {Object} obj * @return {Object} * @api public */ exports.pause = function(obj){ var events = []; function onData(){ events.push(['data'].concat(toArray(arguments))); }; function onEnd(){ events.push(['end'].concat(toArray(arguments))); }; obj.on('data', onData); obj.on('end', onEnd); return { end: function(){ obj.removeListener('data', onData); obj.removeListener('end', onEnd); }, resume: function(){ for (var i = 0, len = events.length; i < len; ++i) { obj.emit.apply(obj, events[i]); } } }; }; exports.mime = { /** * Return mime type for the given path, * otherwise default to exports.defaultMime * ("application/octet-stream"). * * @param {String} path * @return {String} * @api public */ type: function getMime(path) { var index = String(path).lastIndexOf("."); if (index < 0) return defaultMime; var type = exports.mime.types[path.substring(index).toLowerCase()] || defaultMime; return (/(text|javascript)/).test(type) ? type + "; charset=utf-8" : type; }, /** * Mime types. */ types: { ".3gp" : "video/3gpp", ".a" : "application/octet-stream", ".ai" : "application/postscript", ".aif" : "audio/x-aiff", ".aiff" : "audio/x-aiff", ".asc" : "application/pgp-signature", ".asf" : "video/x-ms-asf", ".asm" : "text/x-asm", ".asx" : "video/x-ms-asf", ".atom" : "application/atom+xml", ".au" : "audio/basic", ".avi" : "video/x-msvideo", ".bat" : "application/x-msdownload", ".bin" : "application/octet-stream", ".bmp" : "image/bmp", ".bz2" : "application/x-bzip2", ".c" : "text/x-c", ".cab" : "application/vnd.ms-cab-compressed", ".cc" : "text/x-c", ".chm" : "application/vnd.ms-htmlhelp", ".class" : "application/octet-stream", ".com" : "application/x-msdownload", ".conf" : "text/plain", ".cpp" : "text/x-c", ".crt" : "application/x-x509-ca-cert", ".css" : "text/css", ".csv" : "text/csv", ".cxx" : "text/x-c", ".deb" : "application/x-debian-package", ".der" : "application/x-x509-ca-cert", ".diff" : "text/x-diff", ".djv" : "image/vnd.djvu", ".djvu" : "image/vnd.djvu", ".dll" : "application/x-msdownload", ".dmg" : "application/octet-stream", ".doc" : "application/msword", ".dot" : "application/msword", ".dtd" : "application/xml-dtd", ".dvi" : "application/x-dvi", ".ear" : "application/java-archive", ".eml" : "message/rfc822", ".eps" : "application/postscript", ".exe" : "application/x-msdownload", ".f" : "text/x-fortran", ".f77" : "text/x-fortran", ".f90" : "text/x-fortran", ".flv" : "video/x-flv", ".for" : "text/x-fortran", ".gem" : "application/octet-stream", ".gemspec" : "text/x-script.ruby", ".gif" : "image/gif", ".gz" : "application/x-gzip", ".h" : "text/x-c", ".hh" : "text/x-c", ".htm" : "text/html", ".html" : "text/html", ".ico" : "image/vnd.microsoft.icon", ".ics" : "text/calendar", ".ifb" : "text/calendar", ".iso" : "application/octet-stream", ".jar" : "application/java-archive", ".java" : "text/x-java-source", ".jnlp" : "application/x-java-jnlp-file", ".jpeg" : "image/jpeg", ".jpg" : "image/jpeg", ".js" : "application/javascript", ".json" : "application/json", ".log" : "text/plain", ".m3u" : "audio/x-mpegurl", ".m4v" : "video/mp4", ".man" : "text/troff", ".manifest": "text/cache-manifest", ".mathml" : "application/mathml+xml", ".mbox" : "application/mbox", ".mdoc" : "text/troff", ".me" : "text/troff", ".mid" : "audio/midi", ".midi" : "audio/midi", ".mime" : "message/rfc822", ".mml" : "application/mathml+xml", ".mng" : "video/x-mng", ".mov" : "video/quicktime", ".mp3" : "audio/mpeg", ".mp4" : "video/mp4", ".mp4v" : "video/mp4", ".mpeg" : "video/mpeg", ".mpg" : "video/mpeg", ".ms" : "text/troff", ".msi" : "application/x-msdownload", ".odp" : "application/vnd.oasis.opendocument.presentation", ".ods" : "application/vnd.oasis.opendocument.spreadsheet", ".odt" : "application/vnd.oasis.opendocument.text", ".ogg" : "application/ogg", ".p" : "text/x-pascal", ".pas" : "text/x-pascal", ".pbm" : "image/x-portable-bitmap", ".pdf" : "application/pdf", ".pem" : "application/x-x509-ca-cert", ".pgm" : "image/x-portable-graymap", ".pgp" : "application/pgp-encrypted", ".pkg" : "application/octet-stream", ".pl" : "text/x-script.perl", ".pm" : "text/x-script.perl-module", ".png" : "image/png", ".pnm" : "image/x-portable-anymap", ".ppm" : "image/x-portable-pixmap", ".pps" : "application/vnd.ms-powerpoint", ".ppt" : "application/vnd.ms-powerpoint", ".ps" : "application/postscript", ".psd" : "image/vnd.adobe.photoshop", ".py" : "text/x-script.python", ".qt" : "video/quicktime", ".ra" : "audio/x-pn-realaudio", ".rake" : "text/x-script.ruby", ".ram" : "audio/x-pn-realaudio", ".rar" : "application/x-rar-compressed", ".rb" : "text/x-script.ruby", ".rdf" : "application/rdf+xml", ".roff" : "text/troff", ".rpm" : "application/x-redhat-package-manager", ".rss" : "application/rss+xml", ".rtf" : "application/rtf", ".ru" : "text/x-script.ruby", ".s" : "text/x-asm", ".sgm" : "text/sgml", ".sgml" : "text/sgml", ".sh" : "application/x-sh", ".sig" : "application/pgp-signature", ".snd" : "audio/basic", ".so" : "application/octet-stream", ".svg" : "image/svg+xml", ".svgz" : "image/svg+xml", ".swf" : "application/x-shockwave-flash", ".t" : "text/troff", ".tar" : "application/x-tar", ".tbz" : "application/x-bzip-compressed-tar", ".tci" : "application/x-topcloud", ".tcl" : "application/x-tcl", ".tex" : "application/x-tex", ".texi" : "application/x-texinfo", ".texinfo" : "application/x-texinfo", ".text" : "text/plain", ".tif" : "image/tiff", ".tiff" : "image/tiff", ".torrent" : "application/x-bittorrent", ".tr" : "text/troff", ".ttf" : "application/x-font-ttf", ".txt" : "text/plain", ".vcf" : "text/x-vcard", ".vcs" : "text/x-vcalendar", ".vrml" : "model/vrml", ".war" : "application/java-archive", ".wav" : "audio/x-wav", ".wma" : "audio/x-ms-wma", ".wmv" : "video/x-ms-wmv", ".wmx" : "video/x-ms-wmx", ".wrl" : "model/vrml", ".wsdl" : "application/wsdl+xml", ".xbm" : "image/x-xbitmap", ".xhtml" : "application/xhtml+xml", ".xls" : "application/vnd.ms-excel", ".xml" : "application/xml", ".xpm" : "image/x-xpixmap", ".xsl" : "application/xml", ".xslt" : "application/xslt+xml", ".yaml" : "text/yaml", ".yml" : "text/yaml", ".zip" : "application/zip" } }; // Works like find on unix. Does a recursive readdir and filters by pattern. exports.find = function find(root, pattern, callback) { function rfind(root, callback) { fs.readdir(root, function (err, files) { if (err) { callback(err); return; } var results = [], counter = 0; files.forEach(function (file) { counter++; function checkCounter() { counter--; if (counter === 0) { callback(null, results); } } var file = root + "/" + file; fs.stat(file, function (err, stat) { if (err) { callback(err); return; } if (stat.isDirectory()) { rfind(file, function (err, files) { if (err) { callback(err); return; } results.push.apply(results, files); checkCounter(); }); checkCounter(); return; } if (pattern.test(file)) { stat.path = file; results.push(stat); } checkCounter(); }); }); }); } rfind(root, function (err, files) { if (err) { callback(err); return; } callback(null, files.map(function (file) { file.path = file.path.substr(root.length); return file; })); }); }; /** * Convert array-like object to an Array. * * node-bench: "16.5 times faster than Array.prototype.slice.call()" * * @param {Object} obj * @return {Array} * @api private */ function toArray(obj){ var len = obj.length , arr = new Array(len); for (var i = 0; i < len; ++i) { arr[i] = obj[i]; } return arr; } /** * Retrun a random int, used by `utils.uid()` * * @param {Number} min * @param {Number} max * @return {Number} * @api private */ function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }