Path: blob/main/src/client/requests/xhr.js
305 views
import EventEmitter from "events";1import HookEvent from "../hook.js";23/**4* @typedef {import('../index').default} UVClient5*/67class Xhr extends EventEmitter {8/**9*10* @param {UVClient} ctx11*/12constructor(ctx) {13super();14this.ctx = ctx;15this.window = ctx.window;16this.XMLHttpRequest = this.window.XMLHttpRequest;17this.xhrProto = this.window.XMLHttpRequest18? this.window.XMLHttpRequest.prototype19: {};20this.open = this.xhrProto.open;21this.abort = this.xhrProto.abort;22this.send = this.xhrProto.send;23this.overrideMimeType = this.xhrProto.overrideMimeType;24this.getAllResponseHeaders = this.xhrProto.getAllResponseHeaders;25this.getResponseHeader = this.xhrProto.getResponseHeader;26this.setRequestHeader = this.xhrProto.setRequestHeader;27this.responseURL = ctx.nativeMethods.getOwnPropertyDescriptor(28this.xhrProto,29"responseURL"30);31this.responseText = ctx.nativeMethods.getOwnPropertyDescriptor(32this.xhrProto,33"responseText"34);35}36override() {37this.overrideOpen();38this.overrideSend();39this.overrideMimeType();40this.overrideGetResHeader();41this.overrideGetResHeaders();42this.overrideSetReqHeader();43}44overrideOpen() {45this.ctx.override(this.xhrProto, "open", (target, that, args) => {46if (2 > args.length) return target.apply(that, args);4748let [method, input, async = true, user = null, password = null] = args;49const event = new HookEvent(50{ method, input, async, user, password },51target,52that53);5455this.emit("open", event);56if (event.intercepted) return event.returnValue;5758return event.target.call(59event.that,60event.data.method,61event.data.input,62event.data.async,63event.data.user,64event.data.password65);66});67}68overrideResponseUrl() {69this.ctx.overrideDescriptor(this.xhrProto, "responseURL", {70get: (target, that) => {71const event = new HookEvent({ value: target.call(that) }, target, that);72this.emit("responseUrl", event);7374if (event.intercepted) return event.returnValue;75return event.data.value;76},77});78}79overrideSend() {80this.ctx.override(this.xhrProto, "send", (target, that, [body = null]) => {81const event = new HookEvent({ body }, target, that);8283this.emit("send", event);84if (event.intercepted) return event.returnValue;8586return event.target.call(event.that, event.data.body);87});88}89overrideSetReqHeader() {90this.ctx.override(91this.xhrProto,92"setRequestHeader",93(target, that, args) => {94if (2 > args.length) return target.apply(that, args);9596let [name, value] = args;97const event = new HookEvent({ name, value }, target, that);9899this.emit("setReqHeader", event);100if (event.intercepted) return event.returnValue;101102return event.target.call(event.that, event.data.name, event.data.value);103}104);105}106overrideGetResHeaders() {107this.ctx.override(108this.xhrProto,109"getAllResponseHeaders",110(target, that) => {111const event = new HookEvent({ value: target.call(that) }, target, that);112113this.emit("getAllResponseHeaders", event);114if (event.intercepted) return event.returnValue;115116return event.data.value;117}118);119}120overrideGetResHeader() {121this.ctx.override(122this.xhrProto,123"getResponseHeader",124(target, that, args) => {125if (!args.length) return target.apply(that, args);126let [name] = args;127128const event = new HookEvent(129{ name, value: target.call(that, name) },130target,131that132);133if (event.intercepted) return event.returnValue;134135return event.data.value;136}137);138}139}140141export default Xhr;142143144