express-disk-cache
Advanced tools
Comparing version 1.1.0 to 1.1.1
@@ -1,8 +0,8 @@ | ||
var Buffer = require("safe-buffer").Buffer; | ||
var basename = require("path").basename; | ||
var on_headers = require("on-headers"); | ||
var join = require("path").join; | ||
var uuid = require("uuid/v1"); | ||
var fs = require("fs-extra"); | ||
var debug = function () {}; | ||
var Buffer = require('safe-buffer').Buffer; | ||
var basename = require('path').basename; | ||
var on_headers = require('on-headers'); | ||
var join = require('path').join; | ||
var uuid = require('uuid/v1'); | ||
var fs = require('fs-extra'); | ||
var debug = function(){}; | ||
@@ -14,24 +14,27 @@ // Regex to check the Cache-Control header to | ||
// Header strings | ||
var CACHE_CONTROL = "Cache-Control"; | ||
var CONTENT_TYPE = "Content-Type"; | ||
var CACHE_CONTROL = 'Cache-Control'; | ||
var CONTENT_TYPE = 'Content-Type'; | ||
module.exports = function (cache_directory) { | ||
var tmp_directory; | ||
if (!cache_directory) throw new Error("Pass a cache directory"); | ||
if (!cache_directory) throw new Error('Pass a cache directory'); | ||
// Ensure the temp directory exists | ||
tmp_directory = join(cache_directory, ".tmp"); | ||
tmp_directory = join(cache_directory, '.tmp'); | ||
fs.ensureDirSync(tmp_directory); | ||
return function disk_cache(req, res, next) { | ||
return function disk_cache (req, res, next){ | ||
var called_end = false; | ||
var stream, final_path, tmp_path, tmp_name, protocol; | ||
var content_type, cache_control, has_max_age, category; | ||
var content_type, cache_control, has_max_age, cache_age; | ||
var _write = res.write; | ||
var _end = res.end; | ||
res.write = function (chunk, encoding) { | ||
debug("write called", chunk, encoding); | ||
debug('write called', chunk, encoding); | ||
// Trigger the onHeaders function below | ||
@@ -45,3 +48,3 @@ // if we have not set any headers ourselves | ||
// below. This prevents a 'double write' | ||
// when calling end with a final chunk. | ||
// when calling end with a final chunk. | ||
// I don't understand why this flag isn't | ||
@@ -52,3 +55,3 @@ // needed when calling the original _write | ||
// The return value of response.write is | ||
// meaningful and tells | ||
// meaningful and tells | ||
// I believe it dictates whether or not the stream | ||
@@ -61,14 +64,15 @@ // is ready to be written too again. So we need to return it | ||
res.end = function (chunk, encoding) { | ||
debug("end called", chunk, encoding); | ||
debug('end called', chunk, encoding); | ||
// This flag is used to prevent a 'double write' | ||
// if response.end is invoked with a chunk of data | ||
// You can end a writeable stream with or without | ||
// You can end a writeable stream with or without | ||
// some final piece of data. Calling res.end | ||
// with a final piece of data neccessarily invokes | ||
// res.write afterwards for a reason I don't | ||
// res.write afterwards for a reason I don't | ||
// quite yet understand, so we set this flag to allow | ||
// our res.write function not to write the data a second time | ||
called_end = true; | ||
// Triggers the onHeaders function below | ||
@@ -78,3 +82,3 @@ // if we have not set any headers ourselves | ||
// We need to create a buffer from the data | ||
// We need to create a buffer from the data | ||
// chunk passed to response.end. I'm not sure exactly | ||
@@ -88,3 +92,3 @@ // why but it's what the compression middleware does. | ||
// Again, like res.write, the return value of the end | ||
// Again, like res.write, the return value of the end | ||
// function is meaningful so don't move this elsewhere | ||
@@ -96,14 +100,15 @@ return _end.call(this, chunk, encoding); | ||
// is cacheable when the headers are sent. | ||
on_headers(res, function onResponseHeaders() { | ||
on_headers(res, function onResponseHeaders () { | ||
// Don't cache requests with sessions. This prevents | ||
// sensitive data from appearing in the site's cache. | ||
if (req.session && req.session.uid) { | ||
debug("has session"); | ||
debug('has session'); | ||
return; | ||
} | ||
} | ||
// Check if the response has the no-cache header set | ||
// Don't cache the response if so! | ||
if (no_cache(req, res)) { | ||
debug("no cache"); | ||
debug('no cache'); | ||
return; | ||
@@ -114,6 +119,6 @@ } | ||
// POST or HEAD requests, ever. | ||
if (req.method !== "GET") { | ||
debug("Non-GET request"); | ||
if (req.method !== 'GET') { | ||
debug('Non-GET request'); | ||
return; | ||
} | ||
} | ||
@@ -123,4 +128,4 @@ // Don't cache 404 pages or other error pages | ||
// code for the cache to send which needlessly complicates it. | ||
if (res.statusCode !== 200 && res.statusCode !== 404) { | ||
debug("BAD status " + req.originalUrl + " " + res.statusCode); | ||
if (res.statusCode !== 200) { | ||
debug('BAD status ' + req.originalUrl + ' ' + res.statusCode); | ||
return; | ||
@@ -131,3 +136,3 @@ } | ||
// when we save the file to disk, the query string ought to be included. | ||
// However, when we do this, NGINX can't determine the correct mimetype | ||
// However, when we do this, NGINX can't determine the correct mimetype | ||
// for a file like /cache/example.com/style.css?foo=123 because its file | ||
@@ -138,4 +143,4 @@ // extension is 'css?foo=123' I should look into whether it is possible | ||
if (Object.keys(req.query).length && req.query.extension === undefined) { | ||
debug("Has query string"); | ||
return; | ||
debug('Has query string'); | ||
return; | ||
} | ||
@@ -154,7 +159,7 @@ | ||
// I suspect this catches an error which results when you flush the | ||
// cache for a given site, whilst caching the response to a request to | ||
// I suspect this catches an error which results when you flush the | ||
// cache for a given site, whilst caching the response to a request to | ||
// a page on the site. Allow a sudden, the file to which the stream | ||
// points will no longer exist. There are probably other errors here too. | ||
stream.on("error", function (err) { | ||
stream.on('error', function(err){ | ||
debug(err); | ||
@@ -166,25 +171,15 @@ stream.close(); | ||
// all the data has been written to the response. | ||
// Now we can move the temporary file to its final location. | ||
stream.on("finish", function onStreamEnd() { | ||
debug("stream has finished"); | ||
// Now we can move the temporary file to its final location. | ||
stream.on('finish', function onStreamEnd () { | ||
debug('stream has finished'); | ||
stream.close(); | ||
content_type = res.getHeader(CONTENT_TYPE); | ||
cache_control = res.getHeader(CACHE_CONTROL); | ||
has_max_age = cache_control && cache_control.indexOf("max-age") > -1; | ||
has_max_age = cache_control && cache_control.indexOf('max-age') > -1; | ||
cache_age = has_max_age ? 'permanent' : 'temporary'; | ||
protocol = req.protocol; | ||
// Determine the category for the response: | ||
// - temporary means don't set a max-age | ||
// - permanent means the file will never change | ||
// - missing means the response was sent with a 404 status | ||
if (res.statusCode === 404) { | ||
category = "missing"; | ||
} else if (has_max_age) { | ||
category = "permanent"; | ||
} else { | ||
category = "temporary"; | ||
} | ||
// Trust header added by proxy indicating that before the proxy | ||
@@ -194,4 +189,4 @@ // the request was over HTTPS. This could be spoofed, but the worst | ||
// to some dumb vulnerability by blindly copying the value of a header... | ||
if (protocol === "http" && req.headers["x-forwarded-proto"] === "https") | ||
protocol = "https"; | ||
if (protocol === 'http' && req.headers['x-forwarded-proto'] === 'https') | ||
protocol = 'https'; | ||
@@ -204,5 +199,5 @@ // We create a directory structure to make life as simple as | ||
cache_directory, | ||
req.hostname, // hostname allows the static file server to | ||
req.hostname, // hostname allows the static file server to | ||
protocol, // protocol to allow us to preserve HTTP -> HTTPS redirects | ||
category, // either permanent, temporary or missing (for 404s) | ||
cache_age, // cache_age, either permanent or temporary | ||
req.originalUrl | ||
@@ -213,4 +208,4 @@ ); | ||
// file for this request. Maps requests to /about to /about/index.html | ||
if (needs_index(content_type, req.path)) { | ||
final_path = join(final_path, "index.html"); | ||
if (needs_index(content_type, req.path)) { | ||
final_path = join(final_path, 'index.html'); | ||
} | ||
@@ -220,14 +215,16 @@ | ||
// containing the full, successfully-sent response to this request. | ||
fs.move(tmp_path, final_path, { overwrite: true }, function (err) { | ||
if (!err) return; // We moved the file successfully | ||
fs.move(tmp_path, final_path, {overwrite: true}, function(err){ | ||
if (!err) return; // We moved the file successfully | ||
// We encountered some file system error moving the temp | ||
// file to its final location in the cache directory. | ||
// file to its final location in the cache directory. | ||
// Remove the temporary output and go on with our lives. | ||
debug(err); | ||
fs.remove(tmp_path, function (err) { | ||
fs.remove(tmp_path, function(err){ | ||
// Nothing else we can really do here | ||
if (err) debug(err); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -240,5 +237,6 @@ }); | ||
// Don't compress for Cache-Control: no-cache | ||
function no_cache(req, res) { | ||
var cache_control = res.getHeader("Cache-Control"); | ||
function no_cache (req, res) { | ||
var cache_control = res.getHeader('Cache-Control'); | ||
// There is no cache control header set, so we default | ||
@@ -251,8 +249,4 @@ // to allowing it. | ||
function needs_index(content_type, path) { | ||
return ( | ||
content_type && | ||
content_type.indexOf("text/html") > -1 && | ||
path.indexOf(".") === -1 | ||
); | ||
function needs_index (content_type, path) { | ||
return content_type && content_type.indexOf('text/html') > -1 && path.indexOf('.') === -1; | ||
} |
{ | ||
"name": "express-disk-cache", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"main": "index.js", | ||
@@ -5,0 +5,0 @@ "license": "CC0", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
18809
221