-
Notifications
You must be signed in to change notification settings - Fork 23
/
digest.ts
82 lines (76 loc) · 2.76 KB
/
digest.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
import { Canceler, RequestConfig, Uploader } from 'ngx-uploadx';
export function readBlob(body: Blob, canceler?: Canceler): Promise<ArrayBuffer> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
if (canceler) {
canceler.onCancel = () => {
reader.abort();
reject('aborted');
};
}
reader.onload = () => resolve(reader.result as ArrayBuffer);
reader.onerror = reject;
reader.readAsArrayBuffer(body);
});
}
export function bufferToHex(buf: ArrayBuffer): string {
return Array.from(new Uint8Array(buf), x => x.toString(16).padStart(2, '0')).join('');
}
export function bufferToBase64(hash: ArrayBuffer): string {
return btoa(String.fromCharCode(...new Uint8Array(hash)));
}
export const hasher = {
lookup: {} as Record<string, { key: string; sha: string }>,
isSupported: window.crypto && !!window.crypto.subtle,
async sha(data: ArrayBuffer): Promise<ArrayBuffer> {
return crypto.subtle.digest('SHA-1', data);
},
digestHex(body: Blob, canceler?: Canceler): Promise<string> {
return readBlob(body, canceler).then(buffer => this.sha(buffer).then(bufferToHex));
},
digestBase64(body: Blob, canceler?: Canceler): Promise<string> {
return readBlob(body, canceler).then(buffer => this.sha(buffer).then(bufferToBase64));
}
};
export async function injectTusChecksumHeader(
this: Uploader,
req: RequestConfig
): Promise<RequestConfig> {
if (hasher.isSupported && req.body instanceof Blob) {
if (this.chunkSize) {
const { body, start } = this.getChunk((this.offset || 0) + this.chunkSize);
hasher.digestBase64(body, req.canceler).then(digest => {
const key = `${body.size}-${start}`;
hasher.lookup[req.url] = { key, sha: digest };
});
}
const key = `${req.body.size}-${this.offset}`;
const sha =
hasher.lookup[req.url]?.key === key
? hasher.lookup[req.url].sha
: await hasher.digestBase64(req.body, req.canceler);
Object.assign(req.headers, { 'Upload-Checksum': `sha1 ${sha}` });
}
return req;
}
export async function injectDigestHeader(
this: Uploader,
req: RequestConfig
): Promise<RequestConfig> {
if (hasher.isSupported && req.body instanceof Blob) {
if (this.chunkSize) {
const { body, start } = this.getChunk((this.offset || 0) + this.chunkSize);
hasher.digestBase64(body, req.canceler).then(digest => {
const key = `${body.size}-${start}`;
hasher.lookup[req.url] = { key, sha: digest };
});
}
const key = `${req.body.size}-${this.offset}`;
const sha =
hasher.lookup[req.url]?.key === key
? hasher.lookup[req.url].sha
: await hasher.digestBase64(req.body, req.canceler);
Object.assign(req.headers, { Digest: `sha=${sha}` });
}
return req;
}