Skip to content

Commit f078f21

Browse files
authored
Merge pull request #11 from ItzNotABug/fix-api-cache-expiry
Fix: Use Custom Expiry if Available
2 parents 4f39498 + 0714b9c commit f078f21

File tree

4 files changed

+37
-9
lines changed

4 files changed

+37
-9
lines changed

middlewares/api-cache/README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ This module allows you to cache API responses for a specified period of time.
55
The responses are cached in memory after the first request, up until the function container is removed.\
66
You can check for `X-APPEXPRESS-API-CACHE` in the response header, the values will be any one of the below -
77

8-
1. `HIT` means the response is cached
9-
2. `MISS` means the response is not cached, probably this is the first request
10-
3. `EXCLUDED` means the request is excluded for caching response via options or response header
8+
1. `HIT` - response is cached
9+
2. `MISS` - response is not cached, probably this is the first request
10+
3. `EXCLUDED` - the request is excluded for caching response via options or response header
11+
4. `IGNORED` - the request method is either `PUT`, `POST` or `DELETE` which are never cached
1112

1213
## Installation
1314

@@ -66,8 +67,8 @@ express.get('/user/code', async (req, res) => {
6667
```javascript
6768
express.get('/search/results', async (req, res) => {
6869
if (apiCache.hasCache(req.url)) {
69-
res.empty();
70-
return;
70+
res.empty();
71+
return;
7172
}
7273

7374
const thirtySeconds = 30 * 1000;

middlewares/api-cache/cache.js

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// noinspection JSUnresolvedReference
1+
// noinspection JSUnresolvedReference, JSUnusedGlobalSymbols
22

33
import * as memoryCache from './memory.js';
44

@@ -69,7 +69,15 @@ export default {
6969
* @param {Object} response - The `ResponseHandler` object.
7070
*/
7171
const serveCacheIfAvailable = (request, response) => {
72-
if (isPathExcluded(request)) return;
72+
if (isPathExcluded(request)) {
73+
response.setHeaders({ CACHE_STATUS_HEADER_KEY: 'EXCLUDED' });
74+
return;
75+
}
76+
77+
if (!isRequestValid(request)) {
78+
response.setHeaders({ CACHE_STATUS_HEADER_KEY: 'IGNORED' });
79+
return;
80+
}
7381

7482
const entry = memoryCache.get(request.url);
7583
if (entry) {
@@ -78,7 +86,7 @@ const serveCacheIfAvailable = (request, response) => {
7886
if (entry.isInfinite) {
7987
headers['cache-control'] = 'public, immutable';
8088
} else {
81-
const maxAge = Math.round(configOptions.expirationTime / 1000);
89+
const maxAge = Math.round(entry.timeout / 1000);
8290
headers['cache-control'] = `max-age=${maxAge}`;
8391
}
8492
}
@@ -108,6 +116,11 @@ const saveCache = (request, interceptor) => {
108116
return;
109117
}
110118

119+
if (!isRequestValid(request)) {
120+
headers[CACHE_STATUS_HEADER_KEY] = 'IGNORED';
121+
return;
122+
}
123+
111124
const excludeCache = headers['apicache-exclude'] ?? false;
112125
if (excludeCache) {
113126
headers[CACHE_STATUS_HEADER_KEY] = 'EXCLUDED';
@@ -137,3 +150,15 @@ const isPathExcluded = (request) => {
137150
: exclude.test(request.path),
138151
);
139152
};
153+
154+
/**
155+
* We shouldn't really cache the `PUT`, `POST` or `DELETE` method types.
156+
*
157+
* @param {Object} request - The `RequestHandler` object.
158+
* @returns {boolean} False if the request method is one of the above-mentioned, true otherwise.
159+
*/
160+
const isRequestValid = (request) => {
161+
const method = request.method;
162+
const methodsToExclude = ['put', 'post', 'delete'];
163+
return !methodsToExclude.includes(method);
164+
};

middlewares/api-cache/memory.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* @typedef {Object} CacheEntry
33
* @property {any} value - The cached data.
4+
* @property {number} expiry - The expiry timeout without the timer.
45
* @property {number} timeout - Timeout identifier for the expiration.
56
* @property {boolean} isInfinite - Whether this is an immutable response.
67
*/
@@ -23,6 +24,7 @@ export const add = (timeout, request, interceptor) => {
2324
const { body, headers, statusCode } = interceptor;
2425

2526
memoryCache[key] = {
27+
expiry: timeout,
2628
isInfinite: timeout === 0,
2729
value: { body, headers, statusCode },
2830
timeout: timeout === 0 ? null : setTimeout(() => remove(key), timeout),

middlewares/api-cache/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@itznotabug/appexpress-apicache",
3-
"version": "0.0.2",
3+
"version": "0.0.3",
44
"description": "A api caching middleware for AppExpress.",
55
"author": "@itznotabug",
66
"type": "module",

0 commit comments

Comments
 (0)