-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathhttp_cache.ts
111 lines (97 loc) · 2.55 KB
/
http_cache.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2018-2025 the Deno authors. MIT license.
import { isAbsolute } from "@std/path";
import { assert } from "./util.ts";
import {
type GlobalHttpCache,
instantiate,
type LocalHttpCache,
} from "./lib/deno_cache_dir.generated.js";
export interface HttpCacheCreateOptions {
root: string;
vendorRoot?: string;
readOnly?: boolean;
}
export interface HttpCacheGetOptions {
/** Checksum to evaluate the file against. This is only evaluated for the
* global cache (DENO_DIR) and not the local cache (vendor folder).
*/
checksum?: string;
}
export interface HttpCacheEntry {
headers: Record<string, string>;
content: Uint8Array;
}
export class HttpCache implements Disposable {
#cache: LocalHttpCache | GlobalHttpCache;
#readOnly: boolean | undefined;
private constructor(
cache: LocalHttpCache | GlobalHttpCache,
readOnly: boolean | undefined,
) {
this.#cache = cache;
this.#readOnly = readOnly;
}
static async create(options: HttpCacheCreateOptions): Promise<HttpCache> {
assert(isAbsolute(options.root), "Root must be an absolute path.");
if (options.vendorRoot != null) {
assert(
isAbsolute(options.vendorRoot),
"Vendor root must be an absolute path.",
);
}
const { GlobalHttpCache, LocalHttpCache } = await instantiate();
let cache: LocalHttpCache | GlobalHttpCache;
if (options.vendorRoot != null) {
cache = LocalHttpCache.new(
options.vendorRoot,
options.root,
/* allow global to local copy */ !options.readOnly,
);
} else {
cache = GlobalHttpCache.new(options.root);
}
return new HttpCache(cache, options.readOnly);
}
[Symbol.dispose]() {
this.free();
}
free() {
this.#cache?.free();
}
getHeaders(
url: URL,
): Record<string, string> | undefined {
const map = this.#cache.getHeaders(url.toString());
return map == null ? undefined : Object.fromEntries(map);
}
get(
url: URL,
options?: HttpCacheGetOptions,
): HttpCacheEntry | undefined {
const data = this.#cache.get(
url.toString(),
options?.checksum,
);
return data == null ? undefined : data;
}
set(
url: URL,
headers: Record<string, string>,
content: Uint8Array,
): void {
if (this.#readOnly === undefined) {
this.#readOnly =
(Deno.permissions.querySync({ name: "write" })).state === "denied"
? true
: false;
}
if (this.#readOnly) {
return;
}
this.#cache.set(
url.toString(),
headers,
content,
);
}
}