-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
sw.js
55 lines (51 loc) · 1.56 KB
/
sw.js
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
self.addEventListener('activate', evt => {
return self.clients.claim()
})
self.addEventListener('fetch', evt => {
const { request } = evt
const { url, method, headers } = request
if (!url.includes(self.registration.scope + 'webtorrent/')) return null
function getConsumer(clients) {
return new Promise(rs => {
// Use race condition for whoever controls the response stream
for (const client of clients) {
const mc = new MessageChannel()
const {port1, port2} = mc
port1.onmessage = evt => {
rs([evt.data, mc])
}
client.postMessage({
url,
method,
headers: [...headers],
scope: self.registration.scope
}, [port2])
}
})
}
evt.respondWith(
clients.matchAll({ type: 'window', includeUncontrolled: true })
.then(getConsumer)
.then(([data, mc]) => {
const body = data.body === 'stream' ? new ReadableStream({
pull(controller) {
return new Promise(rs => {
mc.port1.onmessage = evt => {
evt.data
? controller.enqueue(evt.data) // evt.data is Uint8Array
: controller.close() // evt.data is null, means the stream ended
rs()
}
mc.port1.postMessage(true) // send a pull request
})
},
cancel() {
// This event is never executed
mc.port1.postMessage(false) // send a cancel request
}
}) : data.body
return new Response(body, data)
})
.catch(console.error)
)
})