Skip to content

Commit

Permalink
fix: update cache on 304 response
Browse files Browse the repository at this point in the history
These responses mean that the data we have in cache is still valid, but they may come with a fresh maxage policy.
  • Loading branch information
ForbesLindesay committed Apr 12, 2019
1 parent 89f798e commit dde4d50
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/FileCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,33 @@ export default class FileCache implements ICache {
});
}

updateResponseHeaders(url: string, response: Pick<CachedResponse, 'headers' | 'requestTimestamp'>) {
const key = resolve(this._location, getCacheKey(url));
fs.readFile(key + '.json', 'utf8', function (err, data) {
if (err) {
console.warn('Error writing to cache: ' + err.message);
return;
}
let parsed = null;
try {
parsed = JSON.parse(data);
} catch (ex) {
console.warn('Error writing to cache: ' + ex.message);
return;
}
fs.writeFile(key + '.json', JSON.stringify({
statusCode: parsed.statusCode,
headers: response.headers,
requestHeaders: parsed.requestHeaders,
requestTimestamp: response.requestTimestamp
}, null, ' '), function (err) {
if (err) {
console.warn('Error writing to cache: ' + err.message);
}
});
});
}

invalidateResponse(url: string, callback: (err: NodeJS.ErrnoException | null) => void): void {
const key = resolve(this._location, getCacheKey(url));
fs.unlink(key + '.json', (err?: NodeJS.ErrnoException | null) => {
Expand Down
1 change: 1 addition & 0 deletions src/ICache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {CachedResponse} from './CachedResponse';
interface ICache {
getResponse(url: string, cb: (err: Error | null, response: CachedResponse | null) => void): void;
setResponse(url: string, response: CachedResponse | null): void;
updateResponseHeaders?: (url: string, response: Pick<CachedResponse, 'headers' | 'requestTimestamp'>) => void;
invalidateResponse(url: string, cb: (err: Error | null) => void): void;
}

Expand Down
10 changes: 10 additions & 0 deletions src/MemoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ export default class MemoryCache {
callback(null, null);
}
}

updateResponseHeaders(url: string, response: Pick<CachedResponse, 'headers' | 'requestTimestamp'>) {
this._cache[url] = {
...this._cache[url],
headers: response.headers,
requestTimestamp: response.requestTimestamp
};
}

setResponse(url: string, response: CachedResponse): void {
const cache = this._cache;
response.body.pipe(concat((body) => {
Expand All @@ -46,6 +55,7 @@ export default class MemoryCache {
};
}));
}

invalidateResponse(url: string, callback: (err: NodeJS.ErrnoException | null) => void) {
const cache = this._cache;
delete cache[url];
Expand Down
29 changes: 28 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,34 @@ function _request(method: HttpVerb, url: string, options: Options, callback: Cal
if (res.statusCode === 304 && cachedResponse) { // Not Modified
// prevent leakage of file handles
res.body.resume();
const response = new Response(cachedResponse.statusCode, cachedResponse.headers, cachedResponse.body, url);
let resultBody = cachedResponse.body;
const c = (cache as ICache);
if (c.updateResponseHeaders) {
c.updateResponseHeaders(url, {
headers: res.headers,
requestTimestamp: timestamp,
});
} else {
const cachedResponseBody = new PassThrough();
const newResultBody = new PassThrough();
resultBody.on('data', (data: Buffer) => {
cachedResponseBody.write(data);
newResultBody.write(data);
});
resultBody.on('end', () => {
cachedResponseBody.end();
newResultBody.end();
});
resultBody = newResultBody;
(cache as ICache).setResponse(url, {
statusCode: cachedResponse.statusCode,
headers: res.headers,
body: cachedResponseBody,
requestHeaders: cachedResponse.requestHeaders,
requestTimestamp: timestamp,
});
}
const response = new Response(cachedResponse.statusCode, cachedResponse.headers, resultBody, url);
(response as any).fromCache = true;
(response as any).fromNotModified = true;
return callback(null, response);
Expand Down

0 comments on commit dde4d50

Please sign in to comment.