static assets are gzipped and held permanently in memory
This commit is contained in:
parent
0852ab8cff
commit
9768c840b9
2 changed files with 116 additions and 5 deletions
|
|
@ -22,6 +22,7 @@ var crypto = require('crypto');
|
|||
var net = require('net');
|
||||
var safePath = require('./safe_path');
|
||||
var multipart = require('connect-multiparty')();
|
||||
var createGzipStatic = require('./gzip_static');
|
||||
|
||||
module.exports = GrooveBasin;
|
||||
|
||||
|
|
@ -100,9 +101,29 @@ GrooveBasin.prototype.loadConfig = function(cb) {
|
|||
GrooveBasin.prototype.start = function() {
|
||||
var self = this;
|
||||
|
||||
self.loadConfig(function(err) {
|
||||
var pend = new Pend();
|
||||
pend.go(function(cb) {
|
||||
self.loadConfig(cb);
|
||||
});
|
||||
pend.go(function(cb) {
|
||||
var aliases = [];
|
||||
createGzipStatic(path.join(__dirname, "../public"), aliases, function(err, middleware) {
|
||||
if (err) return cb(err);
|
||||
self.app.use(middleware);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
pend.go(function(cb) {
|
||||
var aliases = [['/', '/index.html']];
|
||||
createGzipStatic(path.join(__dirname, "../src/public"), aliases, function(err, middleware) {
|
||||
if (err) return cb(err);
|
||||
self.app.use(middleware);
|
||||
cb();
|
||||
});
|
||||
});
|
||||
pend.wait(function(err) {
|
||||
if (err) {
|
||||
console.error("Error reading config:", err.stack);
|
||||
console.error(err.stack);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -110,9 +131,6 @@ GrooveBasin.prototype.start = function() {
|
|||
self.httpPort = self.config.port;
|
||||
self.db = levelup(self.config.dbPath);
|
||||
|
||||
self.app.use(express.static(path.join(__dirname, '../public')));
|
||||
self.app.use(express.static(path.join(__dirname, '../src/public')));
|
||||
|
||||
self.initializeDownload();
|
||||
self.initializeUpload();
|
||||
|
||||
|
|
|
|||
93
lib/gzip_static.js
Normal file
93
lib/gzip_static.js
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
var zlib = require('zlib');
|
||||
var fs = require('fs');
|
||||
var stream = require('stream');
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var Pend = require('pend');
|
||||
var findit = require('findit');
|
||||
|
||||
module.exports = createGzipStaticMiddleware;
|
||||
|
||||
function createGzipStaticMiddleware(dir, aliases, cb) {
|
||||
var cache = {};
|
||||
var pend = new Pend();
|
||||
var walker = findit(dir);
|
||||
walker.on('file', function(file) {
|
||||
if (ignoreFile(file)) return;
|
||||
var relName = '/' + path.relative(dir, file);
|
||||
var raw = new Sink();
|
||||
var gzipped = new Sink();
|
||||
var inStream = fs.createReadStream(file);
|
||||
inStream.on('error', function(err) {
|
||||
if (err.code === 'EISDIR') {
|
||||
delete cache[relName];
|
||||
return;
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
cache[relName] = {
|
||||
raw: raw,
|
||||
gzipped: gzipped,
|
||||
}
|
||||
pend.go(function(cb) {
|
||||
inStream.pipe(raw);
|
||||
raw.once('finish', cb);
|
||||
});
|
||||
pend.go(function(cb) {
|
||||
inStream.pipe(zlib.createGzip()).pipe(gzipped);
|
||||
gzipped.once('finish', cb);
|
||||
});
|
||||
});
|
||||
walker.on('end', function() {
|
||||
pend.wait(function(err) {
|
||||
if (err) return cb(err);
|
||||
aliases.forEach(function(alias) {
|
||||
cache[alias[0]] = cache[alias[1]];
|
||||
});
|
||||
cb(null, middleware);
|
||||
});
|
||||
function middleware(req, resp, next) {
|
||||
var c = cache[req.url];
|
||||
if (!c) return next();
|
||||
var sink;
|
||||
if (req.headers['accept-encoding'] == null) {
|
||||
console.log("sent raw");
|
||||
sink = c.raw;
|
||||
} else {
|
||||
console.log("sent gzipped");
|
||||
sink = c.gzipped;
|
||||
resp.setHeader('content-encoding', 'gzip');
|
||||
}
|
||||
sink.createReadStream().pipe(resp);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
util.inherits(Sink, stream.Writable);
|
||||
function Sink(options) {
|
||||
stream.Writable.call(this, options);
|
||||
this.buffer = [];
|
||||
}
|
||||
|
||||
Sink.prototype._write = function(chunk, encoding, callback) {
|
||||
this.buffer.push(chunk);
|
||||
callback();
|
||||
};
|
||||
|
||||
Sink.prototype.createReadStream = function(options) {
|
||||
var s = new stream.Readable(options);
|
||||
s.buffer = this.buffer;
|
||||
s._read = function(size) {
|
||||
for (var i = 0; i < s.buffer.length; i += 1) {
|
||||
s.push(s.buffer[i]);
|
||||
}
|
||||
s.push(null);
|
||||
};
|
||||
return s;
|
||||
};
|
||||
|
||||
function ignoreFile(file) {
|
||||
var basename = path.basename(file);
|
||||
return /^\./.test(basename) || /~$/.test(file);
|
||||
}
|
||||
Loading…
Reference in a new issue