From 2e60c7b211ad31de8412f9e79dd32a46599115ef Mon Sep 17 00:00:00 2001
From: yutak23 <79501292+yutak23@users.noreply.github.com>
Date: Thu, 11 Jan 2024 23:47:00 +0900
Subject: [PATCH] feat: content-type are also cached (#59)
---
index.js | 4 +-
test/app-cache.js | 29 ++++++++++++
test/index.js | 29 ++++++++++++
test/params.js | 40 ++++++++++++++++
test/ttls.js | 118 +++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 218 insertions(+), 2 deletions(-)
diff --git a/index.js b/index.js
index 774db5c..9e92b03 100644
--- a/index.js
+++ b/index.js
@@ -65,6 +65,7 @@ module.exports.cacheSeconds = function (secondsTTL, cacheKey) {
if (value) {
// returns the value immediately
debug('hit!!', key)
+ if (value.contentType) res.set('Content-Type', value.contentType)
if (value.isJson) {
res.status(value.status).json(value.body)
} else {
@@ -102,7 +103,7 @@ module.exports.cacheSeconds = function (secondsTTL, cacheKey) {
didHandle = true
const body = data instanceof Buffer ? data.toString() : data
- if (res.statusCode < 400) cacheStore.set(key, { status: res.statusCode, body: body, isJson: isJson }, ttl)
+ if (res.statusCode < 400) cacheStore.set(key, { status: res.statusCode, body: body, isJson: isJson, contentType: res.getHeader('Content-Type') }, ttl)
// send this response to everyone in the queue
drainQueue(key)
@@ -180,6 +181,7 @@ module.exports.cacheSeconds = function (secondsTTL, cacheKey) {
return cacheStore.get(key).then((cachedValue) => {
const value = cachedValue || {}
debug('>> queued hit:', key, value.length)
+ if (value.contentType) res.set('Content-Type', value.contentType)
if (value.isJson) {
res.status(value.status || 200).json(value.body)
} else {
diff --git a/test/app-cache.js b/test/app-cache.js
index 3bb8a03..6a1636d 100644
--- a/test/app-cache.js
+++ b/test/app-cache.js
@@ -6,6 +6,7 @@ var request = require('supertest'),
var hitIndex = 0;
var noContentIndex = 0;
+var contentTypeIndex = 0;
var app = express();
var agent = request.agent(app);
@@ -43,6 +44,12 @@ describe('App-level cache:', function () {
res.status(204).json();
});
+ app.get('/content-type', function (req, res) {
+ contentTypeIndex++;
+ res.set('Content-Type', 'application/xml');
+ res.send('This is some content')
+ });
+
it('1st res.send', function (done) {
agent
.get('/app-test')
@@ -138,4 +145,26 @@ describe('App-level cache:', function () {
done()
})
})
+
+ it('1st content-type', function (done) {
+ agent
+ .get('/content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ })
+
+ it('2st content-type', function (done) {
+ agent
+ .get('/content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ })
});
diff --git a/test/index.js b/test/index.js
index 3250423..27c8308 100644
--- a/test/index.js
+++ b/test/index.js
@@ -9,6 +9,7 @@ let testindex = 0
let noContentIndex = 0
let paramTestindex = 0
let testindexRemove = 0
+let contentTypeIndex = 0
describe('# RouteCache middleware test', function () {
const app = express()
@@ -31,6 +32,12 @@ describe('# RouteCache middleware test', function () {
res.status(204).send()
})
+ app.get('/content-type', routeCache.cacheSeconds(10), function (req, res) {
+ contentTypeIndex++
+ res.set('Content-Type', 'application/xml')
+ res.send('This is some content')
+ })
+
app.get('/500', routeCache.cacheSeconds(10), function (req, res) {
res.status(500).send('Internal server error: ' + Math.random())
})
@@ -109,6 +116,28 @@ describe('# RouteCache middleware test', function () {
})
})
+ it('1st content-type', function (done) {
+ agent
+ .get('/content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ })
+
+ it('2st content-type', function (done) {
+ agent
+ .get('/content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ })
+
it('1st Redirect to hello', function (done) {
agent
.get('/redirect-to-hello')
diff --git a/test/params.js b/test/params.js
index 7eb1a45..86e65b1 100644
--- a/test/params.js
+++ b/test/params.js
@@ -6,6 +6,7 @@ var request = require('supertest'),
var paramTestIndex = 0
var noContentIndex = 0
+var contentTypeIndex = 0
describe('Params / Querystrings', function () {
var app = express()
@@ -20,6 +21,12 @@ describe('Params / Querystrings', function () {
res.status(204).send()
})
+ app.get('/params-content-type', routeCache.cacheSeconds(10, '/params-test-content-type'), function (req, res) {
+ contentTypeIndex++
+ res.set('Content-Type', 'application/xml')
+ res.send('This is some content')
+ })
+
var agent = request.agent(app)
it('without params', function (done) {
@@ -69,4 +76,37 @@ describe('Params / Querystrings', function () {
done()
})
})
+
+ it('content-type without params', function (done) {
+ agent
+ .get('/params-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ })
+
+ it('content-type with a=1', function (done) {
+ agent
+ .get('/params-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ })
+
+ it('content-type with a=2', function (done) {
+ agent
+ .get('/params-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ })
})
diff --git a/test/ttls.js b/test/ttls.js
index 6c98b6a..7d1cef7 100644
--- a/test/ttls.js
+++ b/test/ttls.js
@@ -13,6 +13,7 @@ describe('TTL:', function () {
context('disabled (-1)', function () {
var hitIndex = 0;
var noContentIndex = 0;
+ var contentTypeIndex = 0;
app.get('/cache-disabled', routeCache.cacheSeconds(-1), function (req, res) {
hitIndex++;
@@ -24,6 +25,12 @@ describe('TTL:', function () {
res.status(204).send();
});
+ app.get('/cache-disabled-content-type', routeCache.cacheSeconds(-1), function (req, res) {
+ contentTypeIndex++
+ res.set('Content-Type', 'application/xml')
+ res.send('This is some content')
+ })
+
it('Should get Hit #1', function (done) {
agent
.get('/cache-disabled')
@@ -62,11 +69,36 @@ describe('TTL:', function () {
});
});
+ it('Should contentTypeIndex is 1', function (done) {
+ agent
+ .get('/cache-disabled-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ });
+
+ it('Should contentTypeIndex is 2 (after nextTick)', function (done) {
+
+ process.nextTick(function () {
+ agent
+ .get('/cache-disabled-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 2)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ });
+ });
})
context('zero', function () {
var hitIndex = 0;
var noContentIndex = 0;
+ var contentTypeIndex = 0;
app.get('/cache-zero', routeCache.cacheSeconds(0), function (req, res) {
hitIndex++;
@@ -78,6 +110,12 @@ describe('TTL:', function () {
res.status(204).send();
});
+ app.get('/cache-zero-content-type', routeCache.cacheSeconds(0), function (req, res) {
+ contentTypeIndex++
+ res.set('Content-Type', 'application/xml')
+ res.send('This is some content')
+ })
+
it('Should get Hit #1', function (done) {
agent
.get('/cache-zero')
@@ -138,11 +176,48 @@ describe('TTL:', function () {
}, 200);
});
+ it('Should contentTypeIndex is 1', function (done) {
+ agent
+ .get('/cache-zero-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ });
+
+ it('Should contentTypeIndex is 1 (after nextTick)', function (done) {
+ process.nextTick(function () {
+ agent
+ .get('/cache-zero-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ });
+ });
+
+ it('Should contentTypeIndex is 2 (after 200ms delay)', function (done) {
+ setTimeout(function () {
+ agent
+ .get('/cache-zero-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 2)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ }, 200);
+ });
})
context('1 second:', function () {
var hitIndex = 0;
var noContentIndex = 0;
+ var contentTypeIndex = 0;
app.get('/cache-1s', routeCache.cacheSeconds(1), function (req, res) {
hitIndex++;
@@ -154,6 +229,12 @@ describe('TTL:', function () {
res.status(204).send();
});
+ app.get('/cache-1s-content-type', routeCache.cacheSeconds(1), function (req, res) {
+ contentTypeIndex++
+ res.set('Content-Type', 'application/xml')
+ res.send('This is some content')
+ })
+
it('Should get Hit #1', function (done) {
agent
.get('/cache-1s')
@@ -214,6 +295,41 @@ describe('TTL:', function () {
}, 1300);
});
- });
+ it('Should contentTypeIndex is 1', function (done) {
+ agent
+ .get('/cache-1s-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ });
+ it('Should contentTypeIndex is 1 (after 200ms delay)', function (done) {
+ setTimeout(function () {
+ agent
+ .get('/cache-1s-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 1)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ }, 200);
+ });
+
+ it('Should contentTypeIndex is 2 (after 1200ms delay)', function (done) {
+ setTimeout(function () {
+ agent
+ .get('/cache-1s-content-type')
+ .expect(200, (error, response) => {
+ assert.equal(contentTypeIndex, 2)
+ assert.equal(response.headers['content-type'], 'application/xml; charset=utf-8')
+ assert.equal(response.text, 'This is some content')
+ done()
+ })
+ }, 1200);
+ });
+ });
});