Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/mitm/lib/HttpResponseCache.ts
1030 views
1
import IResourceHeaders from '@secret-agent/interfaces/IResourceHeaders';
2
3
// TODO: implement max-age and last-modified cache control https://tools.ietf.org/id/draft-ietf-httpbis-cache-01.html
4
export default class HttpResponseCache {
5
private readonly cache = new Map<string, IResource>();
6
private readonly accessList: string[] = [];
7
8
constructor(readonly maxItems = 500) {}
9
10
public get(url: string): IResource | null {
11
const entry = this.cache.get(url);
12
if (entry) {
13
this.recordAccess(url);
14
}
15
return entry;
16
}
17
18
public add(url: string, file: Buffer, headers: IResourceHeaders): void {
19
const resource = { file } as IResource;
20
for (const [key, value] of Object.entries(headers)) {
21
const lower = key.toLowerCase();
22
const val = value as string;
23
24
if (lower === 'etag') {
25
resource.etag = val;
26
}
27
if (lower === 'content-encoding') {
28
resource.encoding = val;
29
}
30
if (lower === 'content-type') {
31
resource.contentType = val;
32
}
33
if (lower === 'expires') {
34
resource.expires = val;
35
}
36
if (lower === 'last-modified') {
37
resource.lastModified = val;
38
}
39
if (lower === 'cache-control') {
40
resource.cacheControl = val;
41
if (resource.cacheControl.includes('no-store')) {
42
return;
43
}
44
}
45
}
46
if (!resource.etag) return;
47
48
this.cache.set(url, resource);
49
this.recordAccess(url);
50
this.cleanCache();
51
}
52
53
private recordAccess(url: string): void {
54
const idx = this.accessList.indexOf(url);
55
if (idx >= 0) {
56
this.accessList.splice(idx, 1);
57
}
58
this.accessList.unshift(url);
59
}
60
61
private cleanCache(): void {
62
if (this.accessList.length > this.maxItems) {
63
const toDelete = this.accessList.slice(this.maxItems);
64
this.accessList.length = this.maxItems;
65
for (const url of toDelete) {
66
this.cache.delete(url);
67
}
68
}
69
}
70
}
71
72
interface IResource {
73
file: Buffer;
74
etag: string;
75
cacheControl: string;
76
contentType: string;
77
lastModified: string;
78
expires: string;
79
encoding: string;
80
}
81
82