-
Notifications
You must be signed in to change notification settings - Fork 0
/
api-iife.js
121 lines (102 loc) · 3.28 KB
/
api-iife.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class CORSFetch {
_requestId = 1;
constructor() {
window.originalFetch = fetch.bind(window);
window.hookedFetch = this.hookedFetch.bind(this);
this.enableCORS(true);
}
enableCORS(enable) {
window.fetch = enable ? window.hookedFetch : window.originalFetch;
}
async hookedFetch(input, init) {
const _url = input instanceof Request ? input.url : input.toString();
const isHttpRequests = /^https?:\/\//i.test(_url);
// `ipc://localhost/${path}` and `http://ipc.localhost/${path}` are used for Tauri IPC requests
// https://github.com/tauri-apps/tauri/blob/7898b601d14ed62053dd24011fabadf31ec1af45/core/tauri/scripts/core.js#L12
const isTauriIpcRequests =
/^ipc:\/\/localhost\//i.test(_url) ||
/^http:\/\/ipc.localhost\//i.test(_url);
if (!isHttpRequests || isTauriIpcRequests) {
return window.originalFetch(input, init);
}
return new Promise(async (resolve, reject) => {
const requestId = this._requestId++;
const maxRedirections = init?.maxRedirections;
const connectTimeout = init?.connectTimeout;
const proxy = init?.proxy;
// Remove these fields before creating the request
if (init) {
delete init.maxRedirections;
delete init.connectTimeout;
delete init.proxy;
}
const signal = init?.signal;
const headers = !init?.headers
? []
: init.headers instanceof Headers
? Array.from(init.headers.entries())
: Array.isArray(init.headers)
? init.headers
: Object.entries(init.headers);
const mappedHeaders = headers.map(([name, val]) => [
name,
// we need to ensure we have all values as strings
typeof val === "string" ? val : val.toString(),
]);
const req = new Request(input, init);
const buffer = await req.arrayBuffer();
const reqData = buffer.byteLength
? Array.from(new Uint8Array(buffer))
: null;
signal?.addEventListener("abort", async (e) => {
const error = e.target.reason;
this._invoke("plugin:cors-fetch|cancel_cors_request", {
requestId,
}).catch(() => {});
reject(error);
});
const {
status,
statusText,
url,
body,
headers: responseHeaders,
} = await this._invoke("plugin:cors-fetch|cors_request", {
request: {
requestId,
method: req.method,
url: req.url,
headers: mappedHeaders,
data: reqData,
maxRedirections,
connectTimeout,
proxy,
},
});
const res = new Response(
body instanceof ArrayBuffer && body.byteLength
? body
: body instanceof Array && body.length
? new Uint8Array(body)
: null,
{
headers: responseHeaders,
status,
statusText,
}
);
// url is read only but seems like we can do this
Object.defineProperty(res, "url", { value: url });
resolve(res);
});
}
_invoke(cmd, args, options) {
if ("__TAURI__" in window) {
return window.__TAURI_INTERNALS__.invoke(cmd, args, options);
}
}
}
(function () {
const cf = new CORSFetch();
window.enableCORSFetch = cf.enableCORS.bind(cf);
})();