diff --git a/index.js b/index.js index 4f6ca4e..30c66a5 100644 --- a/index.js +++ b/index.js @@ -1,28 +1,52 @@ "use strict"; -var fs = require("fs"); -var path = require("path"); +var etag = require("etag") +var fresh = require("fresh") +var fs = require("fs"); +var path = require("path"); -var script = path.resolve(__dirname + "/dist/index.min.js"); +var minifiedScript = path.resolve(__dirname + "/dist/index.min.js"); +var unminifiedScript = path.resolve(__dirname + "/dist/index.js"); -function init(options, connector, type) { - - var result; - - if (options && options.minify) { - result = fs.readFileSync(script); - } else { - script = path.resolve(__dirname + "/dist/index.js"); - result = fs.readFileSync(script); - } +function headers(res, body){ + res.setHeader("Cache-Control", "public, max-age=0"); + res.setHeader("Content-Type", "text/javascript"); + res.setHeader("ETag", etag(body)); +}; + +function body(options, connector) { + var script = minifiedScript; + if (options && !options.minify) { + script = unminifiedScript; + } + + return connector + fs.readFileSync(script); +} + +function isConditionalGet(req) { + return req.headers["if-none-match"] || req.headers["if-modified-since"]; +} + +function notModified(res) { + res.removeHeader("Content-Type"); + res.statusCode = 304; + res.end(); +} +function init(options, connector, type) { + var requestBody = body(options, connector); if (type && type === "file") { - return connector + result; + return requestBody; } return function (req, res) { - res.setHeader("Content-Type", "text/javascript"); - res.end(connector + result); + headers(res, requestBody); + + if (isConditionalGet(req) && fresh(req.headers, res._headers)) { + return notModified(res); + } + + res.end(requestBody); }; } diff --git a/package.json b/package.json index 8098b59..28947d3 100644 --- a/package.json +++ b/package.json @@ -51,5 +51,8 @@ "vinyl-source-stream": "^1.1.0" }, "keywords": [], - "dependencies": {} + "dependencies": { + "etag": "^1.7.0", + "fresh": "^0.3.0" + } } diff --git a/test/middleware/middleware.js b/test/middleware/middleware.js index 18c7753..72c9471 100644 --- a/test/middleware/middleware.js +++ b/test/middleware/middleware.js @@ -19,10 +19,47 @@ describe("Using the middleware", function () { assert.isFunction(index.middleware); }); - it("should return the JS", function (done) { + it("should return the JS when no cache", function (done) { request(app) .get("/client") .expect("Content-Type", /text\/javascript/) + .expect("Cache-Control", "public, max-age=0") + .expect("ETag", /".*-.*"/) + .expect(200) + .end(function (err, res) { + assert.isTrue(res.text.length > 0); + assert.isTrue(res.text.indexOf("BEFORE") > -1); + done(); + }); + }); + + it("should return not modified if has cache and fresh", function (done) { + var etag = null; + request(app) + .get("/client") + .end(function (err, res) { + etag = res.headers["ETag"]; + }); + + request(app) + .get("/client") + .set("If-None-Match", etag) + .expect("Cache-Control", "public, max-age=0") + .expect("ETag", /".*-.*"/) + .expect(304) + .end(function (err, res) { + assert.isUndefined(res.headers["Content-Type"]); + done(); + }); + }); + + it("should return the JS if has cache and not fresh", function (done) { + request(app) + .get("/client") + .set("If-None-Match", "Different-ETag") + .expect("Content-Type", /text\/javascript/) + .expect("Cache-Control", "public, max-age=0") + .expect("ETag", /".*-.*"/) .expect(200) .end(function (err, res) { assert.isTrue(res.text.length > 0);