node powered mobile
TRANSCRIPT
![Page 1: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/1.jpg)
Node Powered MobileBy Tim Caswell
Saturday, June 5, 2010
![Page 2: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/2.jpg)
Node Powered MobileBy Tim Caswell
Saturday, June 5, 2010
![Page 3: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/3.jpg)
Simple but Different
Saturday, June 5, 2010
![Page 4: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/4.jpg)
What is needed
Saturday, June 5, 2010
![Page 5: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/5.jpg)
What is needed• Simple Interface
• Light Code
• Networked Data
• Real-Time Data
• Free Deployment
• Open Workflow
Saturday, June 5, 2010
![Page 6: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/6.jpg)
What is needed• Simple Interface
• Light Code
• Networked Data
• Real-Time Data
• Free Deployment
• Open Workflow
• HTML, SVG, CSS
• JavaScript
• HTTP Services
• PubSub
• Browser Apps
• It’s just text!
Saturday, June 5, 2010
![Page 7: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/7.jpg)
ConnectWe’ll use a new node
framework that “connects” the mobile browser to data
on the server.
Saturday, June 5, 2010
![Page 8: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/8.jpg)
It’s like Japanese LegosSaturday, June 5, 2010
![Page 9: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/9.jpg)
Connect.createServer([ {filter: "log"}, {filter: "body-decoder"}, {filter: "conditional-get"}, {filter: "cache"}, {filter: "gzip"}, {provider: "cache-manifest", root: root}, {provider: "static", root: root}]);
Pre-Built Blocks
Saturday, June 5, 2010
![Page 10: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/10.jpg)
And easy too!Saturday, June 5, 2010
![Page 11: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/11.jpg)
method-override.jsvar key;// Initialize any state (on server startup)exports.setup = function (env) { key = this.key || "_method";};// Modify the request stream (on request)exports.handle = function(err, req, res, next){ if (key in req.body) { req.method = req.body[key].toUpperCase(); } next();};
Saturday, June 5, 2010
![Page 12: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/12.jpg)
response-time.jsexports.handle = function(err, req, res, next){ var start = new Date, writeHead = res.writeHead;
res.writeHead = function(code, headers){ res.writeHead = writeHead; headers['X-Response-Time'] = (new Date - start) + "ms"; res.writeHead(code, headers); };
next();};
Saturday, June 5, 2010
![Page 13: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/13.jpg)
Well, actually, it’s not always easy.
Saturday, June 5, 2010
![Page 14: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/14.jpg)
static.js
Saturday, June 5, 2010
![Page 15: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/15.jpg)
static.jsvar fs = require('fs'), Url = require('url'), Path = require('path');
var lifetime = 1000 * 60 * 60; // 1 hour browser cache lifetime
var DEFAULT_MIME = 'application/octet-stream';
module.exports = {
setup: function (env) { this.root = this.root || process.cwd(); },
handle: function (err, req, res, next) { // Skip on error if (err) { next(); return; } var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'), filename = Path.join(this.root, pathname);
if (filename[filename.length - 1] === "/") { filename += "index.html"; }
Saturday, June 5, 2010
![Page 16: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/16.jpg)
static.js // Buffer any events that fire while waiting on the stat. var events = []; function onData() { events.push(["data"].concat(Array.prototype.slice.call(arguments))); } function onEnd() { events.push(["end"].concat(Array.prototype.slice.call(arguments))); } req.addListener("data", onData); req.addListener("end", onEnd);
fs.stat(filename, function (err, stat) {
// Stop buffering events req.removeListener("data", onData); req.removeListener("end", onEnd);
// Fall through for missing files, thow error for other problems if (err) { if (err.errno === process.ENOENT) { next(); // Refire the buffered events events.forEach(function (args) { req.emit.apply(req, args); }); return;
var fs = require('fs'), Url = require('url'), Path = require('path');
var lifetime = 1000 * 60 * 60; // 1 hour browser cache lifetime
var DEFAULT_MIME = 'application/octet-stream';
module.exports = {
setup: function (env) { this.root = this.root || process.cwd(); },
handle: function (err, req, res, next) { // Skip on error if (err) { next(); return; } var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'), filename = Path.join(this.root, pathname);
if (filename[filename.length - 1] === "/") { filename += "index.html"; }
Saturday, June 5, 2010
![Page 17: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/17.jpg)
static.js // Buffer any events that fire while waiting on the stat. var events = []; function onData() { events.push(["data"].concat(Array.prototype.slice.call(arguments))); } function onEnd() { events.push(["end"].concat(Array.prototype.slice.call(arguments))); } req.addListener("data", onData); req.addListener("end", onEnd);
fs.stat(filename, function (err, stat) {
// Stop buffering events req.removeListener("data", onData); req.removeListener("end", onEnd);
// Fall through for missing files, thow error for other problems if (err) { if (err.errno === process.ENOENT) { next(); // Refire the buffered events events.forEach(function (args) { req.emit.apply(req, args); }); return;
} next(err); return; }
// Serve the file directly using buffers fs.readFile(filename, function (err, data) { if (err) { next(err); return; } res.writeHead(200, { "Content-Type": Mime.type(filename), "Content-Length": data.length, "Last-Modified": stat.mtime.toUTCString(), // Cache in browser for 1 year "Cache-Control": "public max-age=" + 31536000 }); res.end(data); }); }); }
var fs = require('fs'), Url = require('url'), Path = require('path');
var lifetime = 1000 * 60 * 60; // 1 hour browser cache lifetime
var DEFAULT_MIME = 'application/octet-stream';
module.exports = {
setup: function (env) { this.root = this.root || process.cwd(); },
handle: function (err, req, res, next) { // Skip on error if (err) { next(); return; } var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'), filename = Path.join(this.root, pathname);
if (filename[filename.length - 1] === "/") { filename += "index.html"; }
Saturday, June 5, 2010
![Page 18: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/18.jpg)
static.js // Buffer any events that fire while waiting on the stat. var events = []; function onData() { events.push(["data"].concat(Array.prototype.slice.call(arguments))); } function onEnd() { events.push(["end"].concat(Array.prototype.slice.call(arguments))); } req.addListener("data", onData); req.addListener("end", onEnd);
fs.stat(filename, function (err, stat) {
// Stop buffering events req.removeListener("data", onData); req.removeListener("end", onEnd);
// Fall through for missing files, thow error for other problems if (err) { if (err.errno === process.ENOENT) { next(); // Refire the buffered events events.forEach(function (args) { req.emit.apply(req, args); }); return;
} next(err); return; }
// Serve the file directly using buffers fs.readFile(filename, function (err, data) { if (err) { next(err); return; } res.writeHead(200, { "Content-Type": Mime.type(filename), "Content-Length": data.length, "Last-Modified": stat.mtime.toUTCString(), // Cache in browser for 1 year "Cache-Control": "public max-age=" + 31536000 }); res.end(data); }); }); }
};
// Mini mime module for static file servingvar Mime = {
type: function getMime(path) { var index = path.lastIndexOf("."); if (index < 0) { return DEFAULT_MIME; } var type = Mime.TYPES[path.substring(index).toLowerCase()] || DEFAULT_MIME; return (/(text|javascript)/).test(type) ? type + "; charset=utf-8" : type; },
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",
var fs = require('fs'), Url = require('url'), Path = require('path');
var lifetime = 1000 * 60 * 60; // 1 hour browser cache lifetime
var DEFAULT_MIME = 'application/octet-stream';
module.exports = {
setup: function (env) { this.root = this.root || process.cwd(); },
handle: function (err, req, res, next) { // Skip on error if (err) { next(); return; } var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'), filename = Path.join(this.root, pathname);
if (filename[filename.length - 1] === "/") { filename += "index.html"; }
Saturday, June 5, 2010
![Page 19: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/19.jpg)
static.js ".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", ".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" }};
// Buffer any events that fire while waiting on the stat. var events = []; function onData() { events.push(["data"].concat(Array.prototype.slice.call(arguments))); } function onEnd() { events.push(["end"].concat(Array.prototype.slice.call(arguments))); } req.addListener("data", onData); req.addListener("end", onEnd);
fs.stat(filename, function (err, stat) {
// Stop buffering events req.removeListener("data", onData); req.removeListener("end", onEnd);
// Fall through for missing files, thow error for other problems if (err) { if (err.errno === process.ENOENT) { next(); // Refire the buffered events events.forEach(function (args) { req.emit.apply(req, args); }); return;
} next(err); return; }
// Serve the file directly using buffers fs.readFile(filename, function (err, data) { if (err) { next(err); return; } res.writeHead(200, { "Content-Type": Mime.type(filename), "Content-Length": data.length, "Last-Modified": stat.mtime.toUTCString(), // Cache in browser for 1 year "Cache-Control": "public max-age=" + 31536000 }); res.end(data); }); }); }
};
// Mini mime module for static file servingvar Mime = {
type: function getMime(path) { var index = path.lastIndexOf("."); if (index < 0) { return DEFAULT_MIME; } var type = Mime.TYPES[path.substring(index).toLowerCase()] || DEFAULT_MIME; return (/(text|javascript)/).test(type) ? type + "; charset=utf-8" : type; },
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",
var fs = require('fs'), Url = require('url'), Path = require('path');
var lifetime = 1000 * 60 * 60; // 1 hour browser cache lifetime
var DEFAULT_MIME = 'application/octet-stream';
module.exports = {
setup: function (env) { this.root = this.root || process.cwd(); },
handle: function (err, req, res, next) { // Skip on error if (err) { next(); return; } var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'), filename = Path.join(this.root, pathname);
if (filename[filename.length - 1] === "/") { filename += "index.html"; }
Saturday, June 5, 2010
![Page 20: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/20.jpg)
static.js ".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", ".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" }};
// Buffer any events that fire while waiting on the stat. var events = []; function onData() { events.push(["data"].concat(Array.prototype.slice.call(arguments))); } function onEnd() { events.push(["end"].concat(Array.prototype.slice.call(arguments))); } req.addListener("data", onData); req.addListener("end", onEnd);
fs.stat(filename, function (err, stat) {
// Stop buffering events req.removeListener("data", onData); req.removeListener("end", onEnd);
// Fall through for missing files, thow error for other problems if (err) { if (err.errno === process.ENOENT) { next(); // Refire the buffered events events.forEach(function (args) { req.emit.apply(req, args); }); return;
} next(err); return; }
// Serve the file directly using buffers fs.readFile(filename, function (err, data) { if (err) { next(err); return; } res.writeHead(200, { "Content-Type": Mime.type(filename), "Content-Length": data.length, "Last-Modified": stat.mtime.toUTCString(), // Cache in browser for 1 year "Cache-Control": "public max-age=" + 31536000 }); res.end(data); }); }); }
".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",
};
// Mini mime module for static file servingvar Mime = {
type: function getMime(path) { var index = path.lastIndexOf("."); if (index < 0) { return DEFAULT_MIME; } var type = Mime.TYPES[path.substring(index).toLowerCase()] || DEFAULT_MIME; return (/(text|javascript)/).test(type) ? type + "; charset=utf-8" : type; },
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",
var fs = require('fs'), Url = require('url'), Path = require('path');
var lifetime = 1000 * 60 * 60; // 1 hour browser cache lifetime
var DEFAULT_MIME = 'application/octet-stream';
module.exports = {
setup: function (env) { this.root = this.root || process.cwd(); },
handle: function (err, req, res, next) { // Skip on error if (err) { next(); return; } var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'), filename = Path.join(this.root, pathname);
if (filename[filename.length - 1] === "/") { filename += "index.html"; }
Saturday, June 5, 2010
![Page 21: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/21.jpg)
static.js ".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", ".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" }};
// Buffer any events that fire while waiting on the stat. var events = []; function onData() { events.push(["data"].concat(Array.prototype.slice.call(arguments))); } function onEnd() { events.push(["end"].concat(Array.prototype.slice.call(arguments))); } req.addListener("data", onData); req.addListener("end", onEnd);
fs.stat(filename, function (err, stat) {
// Stop buffering events req.removeListener("data", onData); req.removeListener("end", onEnd);
// Fall through for missing files, thow error for other problems if (err) { if (err.errno === process.ENOENT) { next(); // Refire the buffered events events.forEach(function (args) { req.emit.apply(req, args); }); return;
} next(err); return; }
// Serve the file directly using buffers fs.readFile(filename, function (err, data) { if (err) { next(err); return; } res.writeHead(200, { "Content-Type": Mime.type(filename), "Content-Length": data.length, "Last-Modified": stat.mtime.toUTCString(), // Cache in browser for 1 year "Cache-Control": "public max-age=" + 31536000 }); res.end(data); }); }); }
".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",
};
// Mini mime module for static file servingvar Mime = {
type: function getMime(path) { var index = path.lastIndexOf("."); if (index < 0) { return DEFAULT_MIME; } var type = Mime.TYPES[path.substring(index).toLowerCase()] || DEFAULT_MIME; return (/(text|javascript)/).test(type) ? type + "; charset=utf-8" : type; },
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",
var fs = require('fs'), Url = require('url'), Path = require('path');
var lifetime = 1000 * 60 * 60; // 1 hour browser cache lifetime
var DEFAULT_MIME = 'application/octet-stream';
module.exports = {
setup: function (env) { this.root = this.root || process.cwd(); },
handle: function (err, req, res, next) { // Skip on error if (err) { next(); return; } var url = Url.parse(req.url);
var pathname = url.pathname.replace(/\.\.+/g, '.'), filename = Path.join(this.root, pathname);
if (filename[filename.length - 1] === "/") { filename += "index.html"; }
Saturday, June 5, 2010
![Page 22: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/22.jpg)
• Authentication
• Authorization
• Body Decoder
• Cache
• Conditional Get
• Debug
• Error Handler
• Gzip
• Log
• Method Override
• Response Time
• Session
Built-in Filter Modules
Saturday, June 5, 2010
![Page 23: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/23.jpg)
• Static
• Rest
• Router
• PubSub
• Cache Manifest
• Direct
• JSON-RPC
• More...
Built-in Data Providers
Saturday, June 5, 2010
![Page 24: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/24.jpg)
Raphaël JSRaphaël is a small JavaScript library that should simplify your work with vector graphics on the web.
Saturday, June 5, 2010
![Page 25: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/25.jpg)
Multi-Touch Vectors
http://vimeo.com/11610421
Saturday, June 5, 2010
![Page 26: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/26.jpg)
multitouch-demo.jswindow.onload = function () { var R = Raphael(0, 0, "100%", "100%"), r = R.circle(100, 100, 50), g = R.circle(210, 100, 50), b = R.circle(320, 100, 50), p = R.circle(430, 100, 50); var start = function () { this.ox = this.attr("cx"); this.oy = this.attr("cy"); this.animate({r: 70, opacity: .25}, 500, ">"); }, move = function (dx, dy) { this.attr({cx: this.ox + dx, cy: this.oy + dy}); }, up = function () { this.animate({r: 50, opacity: .5}, 500, ">"); }; R.set(r, g, b, p).drag(move, start, up);};
Saturday, June 5, 2010
![Page 27: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/27.jpg)
Creating Shapesvar R = Raphael(0, 0, "100%", "100%"), r = R.circle(100, 100, 50) .attr({fill: "hsb(0, 1, 1)"}), g = R.circle(210, 100, 50) .attr({fill: "hsb(.3, 1, 1)"}), b = R.circle(320, 100, 50) .attr({fill: "hsb(.6, 1, 1)"}), p = R.circle(430, 100, 50) .attr({fill: "hsb(.8, 1, 1)"});
Saturday, June 5, 2010
![Page 28: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/28.jpg)
Attaching Eventsfunction start() { this.ox = this.attr("cx"); this.oy = this.attr("cy"); this.animate({r: 70, opacity: .25}, 500, ">");}function move(dx, dy) { this.attr({cx: this.ox + dx, cy: this.oy + dy});}function up() { this.animate({r: 50, opacity: .5}, 500, ">");}R.set(r, g, b, p).drag(move, start, up);
Saturday, June 5, 2010
![Page 29: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/29.jpg)
Let’s combine them!
Saturday, June 5, 2010
![Page 30: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/30.jpg)
• Serving static assets (HTML, CSS, JS)
• Live Interaction (Pub Sub)
• Performance Tweaks (Cache, Gzip)
• Offline Mode (Cache Manifest)
• HTTP Request Logging
Saturday, June 5, 2010
![Page 31: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/31.jpg)
app.js (stack)require.paths.unshift("./lib");var Connect = require('connect');var root = __dirname + "/public";
module.exports = Connect.createServer([ {filter: "log"}, {filter: "body-decoder"}, {provider: "pubsub", route: "/stream", logic: Backend}, {filter: "conditional-get"}, {filter: "cache"}, {filter: "gzip"}, {provider: "cache-manifest", root: root}, {provider: "static", root: root}]);
Saturday, June 5, 2010
![Page 32: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/32.jpg)
app.js (Backend)var Backend = { subscribe: function (subscriber) { if (subscribers.indexOf(subscriber) < 0) { subscribers.push(subscriber); } }, unsubscribe: function (subscriber) { var pos = subscribers.indexOf(subscriber); if (pos >= 0) { subscribers.slice(pos); } }, publish: function (message, callback) { subscribers.forEach(function (subscriber) { subscriber.send(message); }); callback(); }};
Saturday, June 5, 2010
![Page 33: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/33.jpg)
index.html<!DOCTYPE html><html lang="en" manifest="cache.manifest"><head> <meta charset="utf-8" /> <meta name="apple-mobile-web-app-capable" content="yes"> <title>Node + Raphaël</title> <link rel="stylesheet" href="style.css" type="text/css" /> <script src="raphael.js"></script> <script src="client.js"></script></head><body> <div id="holder"></div> </body></html>
Saturday, June 5, 2010
![Page 34: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/34.jpg)
Demo Time!
Saturday, June 5, 2010
![Page 35: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/35.jpg)
http://github.com/extjs/connect
http://twitter.com/creationix
http://raphaeljs.com
http://nodejs.org
Saturday, June 5, 2010
![Page 36: Node Powered Mobile](https://reader033.vdocuments.mx/reader033/viewer/2022042614/5558c45ed8b42a235c8b46c1/html5/thumbnails/36.jpg)
AnyQuestions
?
Saturday, June 5, 2010