Path: blob/main/src/client/requests/fetch.js
305 views
import EventEmitter from "events";1import HookEvent from "../hook.js";23/**4* @typedef {import('../index').default} UVClient5*/67class Fetch extends EventEmitter {8/**9*10* @param {UVClient} ctx11*/12constructor(ctx) {13super();14this.ctx = ctx;15this.window = ctx.window;16this.fetch = this.window.fetch;17this.Request = this.window.Request;18this.Response = this.window.Response;19this.Headers = this.window.Headers;20this.reqProto = this.Request ? this.Request.prototype : {};21this.resProto = this.Response ? this.Response.prototype : {};22this.headersProto = this.Headers ? this.Headers.prototype : {};23this.reqUrl = ctx.nativeMethods.getOwnPropertyDescriptor(24this.reqProto,25"url"26);27this.resUrl = ctx.nativeMethods.getOwnPropertyDescriptor(28this.resProto,29"url"30);31this.reqHeaders = ctx.nativeMethods.getOwnPropertyDescriptor(32this.reqProto,33"headers"34);35this.resHeaders = ctx.nativeMethods.getOwnPropertyDescriptor(36this.resProto,37"headers"38);39}40override() {41this.overrideRequest();42this.overrideUrl();43this.overrideHeaders();44return true;45}46overrideRequest() {47if (!this.fetch) return false;4849this.ctx.override(this.window, "fetch", (target, that, args) => {50if (!args.length || args[0] instanceof this.Request)51return target.apply(that, args);5253let [input, options = {}] = args;54const event = new HookEvent({ input, options }, target, that);5556this.emit("request", event);57if (event.intercepted) return event.returnValue;5859return event.target.call(60event.that,61event.data.input,62event.data.options63);64});6566this.ctx.override(67this.window,68"Request",69(target, that, args) => {70if (!args.length) return new target(...args);7172let [input, options = {}] = args;73const event = new HookEvent({ input, options }, target);7475this.emit("request", event);76if (event.intercepted) return event.returnValue;7778return new event.target(event.data.input, event.data.options);79},80true81);82return true;83}84overrideUrl() {85this.ctx.overrideDescriptor(this.reqProto, "url", {86get: (target, that) => {87const event = new HookEvent({ value: target.call(that) }, target, that);8889this.emit("requestUrl", event);90if (event.intercepted) return event.returnValue;9192return event.data.value;93},94});9596this.ctx.overrideDescriptor(this.resProto, "url", {97get: (target, that) => {98const event = new HookEvent({ value: target.call(that) }, target, that);99100this.emit("responseUrl", event);101if (event.intercepted) return event.returnValue;102103return event.data.value;104},105});106return true;107}108overrideHeaders() {109if (!this.Headers) return false;110111this.ctx.overrideDescriptor(this.reqProto, "headers", {112get: (target, that) => {113const event = new HookEvent({ value: target.call(that) }, target, that);114115this.emit("requestHeaders", event);116if (event.intercepted) return event.returnValue;117118return event.data.value;119},120});121122this.ctx.overrideDescriptor(this.resProto, "headers", {123get: (target, that) => {124const event = new HookEvent({ value: target.call(that) }, target, that);125126this.emit("responseHeaders", event);127if (event.intercepted) return event.returnValue;128129return event.data.value;130},131});132133this.ctx.override(this.headersProto, "get", (target, that, [name]) => {134if (!name) return target.call(that);135const event = new HookEvent(136{ name, value: target.call(that, name) },137target,138that139);140141this.emit("getHeader", event);142if (event.intercepted) return event.returnValue;143144return event.data.value;145});146147this.ctx.override(this.headersProto, "set", (target, that, args) => {148if (2 > args.length) return target.apply(that, args);149150let [name, value] = args;151const event = new HookEvent({ name, value }, target, that);152153this.emit("setHeader", event);154if (event.intercepted) return event.returnValue;155156return event.target.call(event.that, event.data.name, event.data.value);157});158159this.ctx.override(this.headersProto, "has", (target, that, args) => {160if (!args.length) return target.call(that);161let [name] = args;162163const event = new HookEvent(164{ name, value: target.call(that, name) },165target,166that167);168169this.emit("hasHeader", event);170if (event.intercepted) return event.returnValue;171172return event.data;173});174175this.ctx.override(this.headersProto, "append", (target, that, args) => {176if (2 > args.length) return target.apply(that, args);177178let [name, value] = args;179const event = new HookEvent({ name, value }, target, that);180181this.emit("appendHeader", event);182if (event.intercepted) return event.returnValue;183184return event.target.call(event.that, event.data.name, event.data.value);185});186187this.ctx.override(this.headersProto, "delete", (target, that, args) => {188if (!args.length) return target.apply(that, args);189190let [name] = args;191const event = new HookEvent({ name }, target, that);192193this.emit("deleteHeader", event);194if (event.intercepted) return event.returnValue;195196return event.target.call(event.that, event.data.name);197});198199return true;200}201}202203export default Fetch;204205206