Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactoring Client/CDN caching of gzipped files

  • Loading branch information...
commit 63e26cd3b4adfe6eb328cbcaeac5505f463d4fb8 1 parent 73181bc
@tomgco tomgco authored
Showing with 47 additions and 28 deletions.
  1. +1 −0  .gitignore
  2. +26 −22 lib/staticGzip.js
  3. +20 −6 test/staticGzipTest.js
View
1  .gitignore
@@ -10,3 +10,4 @@ Icon?
._*
.Spotlight-V100
.Trashes
+bench/*
View
48 lib/staticGzip.js
@@ -13,11 +13,14 @@ var fs = require('fs'),
path = require('path'),
mime = require('mime'),
compress = require('compress'),
- staticSend;
+ staticSend,
+ removeContentHeaders;
try {
staticSend = require('connect').static.send;
+ removeContentHeaders = require('connect').utils.removeContentHeaders;
} catch (e) {
staticSend = require('express').static.send;
+ removeContentHeaders = require('express').utils.removeContentHeaders;
}
/**
* gzipped cache.
@@ -84,15 +87,20 @@ exports = module.exports = function staticGzip(dirPath, options){
staticSend(req, res, next, o);
}
- function sendGzipped(cacheObj) {
- contentType = contentType + (charset ? '; charset=' + charset : '');
+ function setHeaders(cacheObj) {
res.setHeader('Content-Type', contentType);
res.setHeader('Content-Encoding', 'gzip');
res.setHeader('Vary', 'Accept-Encoding');
res.setHeader('Content-Length', cacheObj.content.length);
- res.setHeader('Last-Modified', cacheObj.mtime);
- res.setHeader('Date', (new Date()).toUTCString());
- res.setHeader('Expires', (new Date((new Date()).getTime()+maxAge)).toUTCString());
+ res.setHeader('Last-Modified', new Date(cacheObj.mtime).toUTCString());
+ res.setHeader('Date', new Date().toUTCString());
+ res.setHeader('Expires', new Date(Date.now() + clientMaxAge).toUTCString());
+ res.setHeader('Cache-Control', 'public, max-age=' + (clientMaxAge / 1000));
+ res.setHeader('ETag', '"' + cacheObj.content.length + '-' + Number(cacheObj.mtime) + '"');
+ }
+
+ function sendGzipped(cacheObj) {
+ setHeaders(cacheObj);
res.end(cacheObj.content, 'binary');
}
@@ -100,7 +108,7 @@ exports = module.exports = function staticGzip(dirPath, options){
gzippo(filename, charset, function(gzippedData) {
gzippoCache[gzipName] = {
'ctime': Date.now(),
- 'mtime': mtime,
+ 'mtime': new Date(mtime).getTime(),
'content': gzippedData
};
sendGzipped(gzippoCache[gzipName]);
@@ -117,6 +125,7 @@ exports = module.exports = function staticGzip(dirPath, options){
contentType = mime.lookup(filename);
charset = mime.charsets.lookup(contentType);
+ contentType = contentType + (charset ? '; charset=' + charset : '');
acceptEncoding = req.headers['accept-encoding'] || '';
if (!contentTypeMatch.test(contentType)) {
@@ -141,25 +150,20 @@ exports = module.exports = function staticGzip(dirPath, options){
if (req.headers['if-modified-since'] &&
gzippoCache[gzipName] &&
- (new Date(gzippoCache[gzipName].mtime)).getTime() <= (new Date(req.headers['if-modified-since'])).getTime()) {
- contentType = contentType + (charset ? '; charset=' + charset : '');
- res.setHeader('Content-Type', contentType);
- res.setHeader('Content-Encoding', 'gzip');
- res.setHeader('Vary', 'Accept-Encoding');
- res.setHeader('Last-Modified', gzippoCache[gzipName].mtime);
- res.setHeader('Date', (new Date()).toUTCString());
- res.setHeader('Expires', (new Date((new Date()).getTime()+maxAge)).toUTCString());
- return res.send(304);
+ +gzippoCache[gzipName].mtime <= new Date(req.headers['if-modified-since']).getTime()) {
+ setHeaders(gzippoCache[gzipName]);
+ removeContentHeaders(res);
+ res.statusCode = 304;
+ return res.end();
}
- //check for pre-compressed file
- //TODO: Look into placing into a loop and using dot notation for speed improvements.
+ //TODO: check for pre-compressed file
if (typeof gzippoCache[gzipName] === 'undefined') {
- gzipAndSend(filename, gzipName, (new Date(stat.mtime)).toUTCString());
+ gzipAndSend(filename, gzipName, stat.mtime.toUTCString());
} else {
- if ((gzippoCache[gzipName].mtime < stat.mtime) ||
- ((gzippoCache[gzipName].ctime + maxAge) < Date.now())) {
- gzipAndSend(filename, gzipName, (new Date(stat.mtime)).toUTCString());
+ if ((gzippoCache[gzipName].mtime < stat.mtime) ||
+ ((gzippoCache[gzipName].ctime + maxAge) < Date.now())) {
+ gzipAndSend(filename, gzipName, stat.mtime.toUTCString());
} else {
sendGzipped(gzippoCache[gzipName]);
}
View
26 test/staticGzipTest.js
@@ -110,28 +110,42 @@ module.exports = {
}
);
},
- 'requesting gzipped utf-8 file second time caches': function() {
+ 'requesting gzipped utf-8 file returns 304': function() {
assert.response(app,
{
url: '/utf8.txt',
headers: {
- 'Accept-Encoding':"gzip",
+ 'Accept-Encoding': "gzip"
}
},
function(res) {
+ res.statusCode.should.equal(200);
assert.response(app,
{
url: '/utf8.txt',
headers: {
- 'Accept-Encoding':"gzip",
- 'If-Modified-Since': 'Mon, 28 Dec 2020 01:00:00 GMT'
+ 'Accept-Encoding': "gzip",
+ 'If-Modified-Since': res.headers['last-modified']
}
},
- function(res) {
- res.statusCode.should.equal(304);
+ function(res2) {
+ res2.statusCode.should.equal(304);
}
);
}
);
+ },
+ 'requesting gzipped utf-8 file returns 200': function() {
+ assert.response(app,
+ {
+ url: '/utf8.txt',
+ headers: {
+ 'Accept-Encoding': "gzip"
+ }
+ },
+ function(res) {
+ res.statusCode.should.equal(200);
+ }
+ );
}
};
Please sign in to comment.
Something went wrong with that request. Please try again.