Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ultraviolet
Path: blob/main/src/client/requests/fetch.js
305 views
1
import EventEmitter from "events";
2
import HookEvent from "../hook.js";
3
4
/**
5
* @typedef {import('../index').default} UVClient
6
*/
7
8
class Fetch extends EventEmitter {
9
/**
10
*
11
* @param {UVClient} ctx
12
*/
13
constructor(ctx) {
14
super();
15
this.ctx = ctx;
16
this.window = ctx.window;
17
this.fetch = this.window.fetch;
18
this.Request = this.window.Request;
19
this.Response = this.window.Response;
20
this.Headers = this.window.Headers;
21
this.reqProto = this.Request ? this.Request.prototype : {};
22
this.resProto = this.Response ? this.Response.prototype : {};
23
this.headersProto = this.Headers ? this.Headers.prototype : {};
24
this.reqUrl = ctx.nativeMethods.getOwnPropertyDescriptor(
25
this.reqProto,
26
"url"
27
);
28
this.resUrl = ctx.nativeMethods.getOwnPropertyDescriptor(
29
this.resProto,
30
"url"
31
);
32
this.reqHeaders = ctx.nativeMethods.getOwnPropertyDescriptor(
33
this.reqProto,
34
"headers"
35
);
36
this.resHeaders = ctx.nativeMethods.getOwnPropertyDescriptor(
37
this.resProto,
38
"headers"
39
);
40
}
41
override() {
42
this.overrideRequest();
43
this.overrideUrl();
44
this.overrideHeaders();
45
return true;
46
}
47
overrideRequest() {
48
if (!this.fetch) return false;
49
50
this.ctx.override(this.window, "fetch", (target, that, args) => {
51
if (!args.length || args[0] instanceof this.Request)
52
return target.apply(that, args);
53
54
let [input, options = {}] = args;
55
const event = new HookEvent({ input, options }, target, that);
56
57
this.emit("request", event);
58
if (event.intercepted) return event.returnValue;
59
60
return event.target.call(
61
event.that,
62
event.data.input,
63
event.data.options
64
);
65
});
66
67
this.ctx.override(
68
this.window,
69
"Request",
70
(target, that, args) => {
71
if (!args.length) return new target(...args);
72
73
let [input, options = {}] = args;
74
const event = new HookEvent({ input, options }, target);
75
76
this.emit("request", event);
77
if (event.intercepted) return event.returnValue;
78
79
return new event.target(event.data.input, event.data.options);
80
},
81
true
82
);
83
return true;
84
}
85
overrideUrl() {
86
this.ctx.overrideDescriptor(this.reqProto, "url", {
87
get: (target, that) => {
88
const event = new HookEvent({ value: target.call(that) }, target, that);
89
90
this.emit("requestUrl", event);
91
if (event.intercepted) return event.returnValue;
92
93
return event.data.value;
94
},
95
});
96
97
this.ctx.overrideDescriptor(this.resProto, "url", {
98
get: (target, that) => {
99
const event = new HookEvent({ value: target.call(that) }, target, that);
100
101
this.emit("responseUrl", event);
102
if (event.intercepted) return event.returnValue;
103
104
return event.data.value;
105
},
106
});
107
return true;
108
}
109
overrideHeaders() {
110
if (!this.Headers) return false;
111
112
this.ctx.overrideDescriptor(this.reqProto, "headers", {
113
get: (target, that) => {
114
const event = new HookEvent({ value: target.call(that) }, target, that);
115
116
this.emit("requestHeaders", event);
117
if (event.intercepted) return event.returnValue;
118
119
return event.data.value;
120
},
121
});
122
123
this.ctx.overrideDescriptor(this.resProto, "headers", {
124
get: (target, that) => {
125
const event = new HookEvent({ value: target.call(that) }, target, that);
126
127
this.emit("responseHeaders", event);
128
if (event.intercepted) return event.returnValue;
129
130
return event.data.value;
131
},
132
});
133
134
this.ctx.override(this.headersProto, "get", (target, that, [name]) => {
135
if (!name) return target.call(that);
136
const event = new HookEvent(
137
{ name, value: target.call(that, name) },
138
target,
139
that
140
);
141
142
this.emit("getHeader", event);
143
if (event.intercepted) return event.returnValue;
144
145
return event.data.value;
146
});
147
148
this.ctx.override(this.headersProto, "set", (target, that, args) => {
149
if (2 > args.length) return target.apply(that, args);
150
151
let [name, value] = args;
152
const event = new HookEvent({ name, value }, target, that);
153
154
this.emit("setHeader", event);
155
if (event.intercepted) return event.returnValue;
156
157
return event.target.call(event.that, event.data.name, event.data.value);
158
});
159
160
this.ctx.override(this.headersProto, "has", (target, that, args) => {
161
if (!args.length) return target.call(that);
162
let [name] = args;
163
164
const event = new HookEvent(
165
{ name, value: target.call(that, name) },
166
target,
167
that
168
);
169
170
this.emit("hasHeader", event);
171
if (event.intercepted) return event.returnValue;
172
173
return event.data;
174
});
175
176
this.ctx.override(this.headersProto, "append", (target, that, args) => {
177
if (2 > args.length) return target.apply(that, args);
178
179
let [name, value] = args;
180
const event = new HookEvent({ name, value }, target, that);
181
182
this.emit("appendHeader", event);
183
if (event.intercepted) return event.returnValue;
184
185
return event.target.call(event.that, event.data.name, event.data.value);
186
});
187
188
this.ctx.override(this.headersProto, "delete", (target, that, args) => {
189
if (!args.length) return target.apply(that, args);
190
191
let [name] = args;
192
const event = new HookEvent({ name }, target, that);
193
194
this.emit("deleteHeader", event);
195
if (event.intercepted) return event.returnValue;
196
197
return event.target.call(event.that, event.data.name);
198
});
199
200
return true;
201
}
202
}
203
204
export default Fetch;
205
206