-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfetch-to-handler.js
100 lines (82 loc) · 2.4 KB
/
fetch-to-handler.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
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
const fs = require('fs')
const { Readable } = require('stream')
module.exports = function fetchToHandler (getFetch, session) {
let hasFetch = null
let loadingFetch = null
async function load () {
if (hasFetch) return hasFetch
if (loadingFetch) return loadingFetch
loadingFetch = Promise.resolve(getFetch()).then((fetch) => {
hasFetch = fetch
loadingFetch = null
return fetch
})
return loadingFetch
}
async function * readBody (body) {
for (const chunk of body) {
if (chunk.bytes) {
yield await Promise.resolve(chunk.bytes)
} else if (chunk.blobUUID) {
yield await session.getBlobData(chunk.blobUUID)
} else if (chunk.file) {
yield * Readable.from(fs.createReadStream(chunk.file))
}
}
}
const close = async () => {
if (loadingFetch) {
await loadingFetch
await close()
} else if (hasFetch) {
if (hasFetch.close) await hasFetch.close()
else if (hasFetch.destroy) await hasFetch.destroy()
}
}
return { handler: protocolHandler, close }
async function protocolHandler (req, sendResponse) {
const headers = {
'Access-Control-Allow-Origin': '*',
'Allow-CSP-From': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Request-Headers': '*'
}
try {
// Lazy load fetch implementation
const fetch = await load()
const { url, headers: requestHeaders, method, uploadData } = req
const body = uploadData ? Readable.from(readBody(uploadData)) : null
const response = await fetch({ url, headers: requestHeaders, method, body, session })
const { status: statusCode, body: responseBody, headers: responseHeaders } = response
for (const [key, value] of responseHeaders) {
if (Array.isArray(value)) {
headers[key] = value[0]
} else {
headers[key] = value
}
}
const isAsync = responseBody[Symbol.asyncIterator]
const data = isAsync ? Readable.from(responseBody, { objectMode: false }) : responseBody
sendResponse({
statusCode,
headers,
data
})
} catch (e) {
console.log(e)
sendResponse({
statusCode: 500,
headers,
data: intoStream(e.stack)
})
}
}
}
function intoStream (data) {
return new Readable({
read () {
this.push(data)
this.push(null)
}
})
}