Skip to content

Commit b1027eb

Browse files
committed
store response data into separate cache key
1 parent a9414e9 commit b1027eb

File tree

1 file changed

+31
-20
lines changed

1 file changed

+31
-20
lines changed

index.js

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const X_CACHE_HIT = 'x-cache-hit'
1111
const CACHE_ETAG = 'etag'
1212
const CACHE_CONTROL = 'cache-control'
1313
const CACHE_IF_NONE_MATCH = 'if-none-match'
14+
const DATA_POSTFIX = '-d'
1415

1516
const middleware = (opts) => async (req, res, next) => {
1617
try {
@@ -30,43 +31,50 @@ const middleware = (opts) => async (req, res, next) => {
3031
// ref cache key on req object
3132
req.cacheKey = key
3233

33-
// try to retrieve cached response
34-
const cached = await get(mcache, key)
34+
// try to retrieve cached response metadata
35+
const metadata = await get(mcache, key)
3536

36-
if (cached) {
37+
if (metadata) {
3738
// respond from cache if there is a hit
38-
let { status, headers, data } = JSON.parse(cached)
39+
const { status, headers, encoding } = JSON.parse(metadata)
3940

4041
// pre-checking If-None-Match header
4142
if (req.headers[CACHE_IF_NONE_MATCH] && req.headers[CACHE_IF_NONE_MATCH] === headers[CACHE_ETAG]) {
4243
res.setHeader('content-length', '0')
4344
res.statusCode = 304
4445
res.end()
4546

46-
return // exit because client cache state matches
47-
}
48-
49-
if (typeof data === 'object' && data.type === 'Buffer') {
50-
data = Buffer.from(data.data)
51-
}
52-
headers[X_CACHE_HIT] = '1'
47+
return
48+
} else {
49+
// try to retrieve cached response data
50+
const payload = await get(mcache, key + DATA_POSTFIX)
51+
if (payload) {
52+
let { data } = JSON.parse(payload)
53+
if (typeof data === 'object' && data.type === 'Buffer') {
54+
data = Buffer.from(data.data)
55+
}
56+
headers[X_CACHE_HIT] = '1'
5357

54-
// set cached response headers
55-
Object.keys(headers).forEach(header => res.setHeader(header, headers[header]))
58+
// set cached response headers
59+
Object.keys(headers).forEach(header => res.setHeader(header, headers[header]))
5660

57-
// send cached payload
58-
req.cacheHit = true
59-
res.statusCode = status
60-
res.end(data)
61+
// send cached payload
62+
req.cacheHit = true
63+
res.statusCode = status
64+
res.end(data, encoding)
6165

62-
return
66+
return
67+
}
68+
}
6369
}
6470

6571
onEnd(res, (payload) => {
6672
if (payload.headers[X_CACHE_EXPIRE]) {
6773
// support service level expiration
6874
const keysPattern = payload.headers[X_CACHE_EXPIRE].replace(/\s/g, '')
69-
const patterns = keysPattern.split(',')
75+
const patterns = keysPattern.split(',').map(pattern =>
76+
pattern.endsWith('*') ? pattern : [pattern, pattern + DATA_POSTFIX])
77+
.flat()
7078
// delete keys on all cache tiers
7179
patterns.forEach(pattern => opts.stores.forEach(store => getKeys(store, pattern).then(keys => mcache.del(keys))))
7280
} else if (payload.headers[X_CACHE_TIMEOUT] || payload.headers[CACHE_CONTROL]) {
@@ -92,7 +100,10 @@ const middleware = (opts) => async (req, res, next) => {
92100
payload.headers[CACHE_ETAG] = Math.random().toString(36).substring(2, 16)
93101
}
94102

95-
// cache response
103+
// cache response data
104+
mcache.set(req.cacheKey + DATA_POSTFIX, JSON.stringify({ data: payload.data }), { ttl })
105+
delete payload.data
106+
// cache response metadata
96107
mcache.set(req.cacheKey, JSON.stringify(payload), { ttl })
97108
}
98109
})

0 commit comments

Comments
 (0)