@@ -11,6 +11,7 @@ const X_CACHE_HIT = 'x-cache-hit'
1111const CACHE_ETAG = 'etag'
1212const CACHE_CONTROL = 'cache-control'
1313const CACHE_IF_NONE_MATCH = 'if-none-match'
14+ const DATA_POSTFIX = '-d'
1415
1516const 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