Skip to content

Instantly share code, notes, and snippets.

@patrickkunka
Created February 28, 2020 15:43
Show Gist options
  • Save patrickkunka/e8014bfbdbceebdf4e42d1fb01958765 to your computer and use it in GitHub Desktop.
Save patrickkunka/e8014bfbdbceebdf4e42d1fb01958765 to your computer and use it in GitHub Desktop.
XHR Proxy
((win) => {
const XMLHttpRequest = win.XMLHttpRequest;
class EventTarget {
listeners = {};
addEventListener(type, listener) {
const listenersOfType = this.listeners[type];
if (typeof listenersOfType === 'undefined') {
this.listeners[type] = [listener];
return;
}
listenersOfType.push(listener);
}
removeEventListener(type, listener) {
const listenersOfType = this.listeners[type];
if (typeof listenersOfType === 'undefined') return;
listenersOfType.splice(listenersOfType.indexOf(listener), 1);
}
dispatchEvent(event) {
const propertyDescriptor = Object.getOwnPropertyDescriptor(
event,
'target'
);
if (!propertyDescriptor || propertyDescriptor.writable) {
Object.defineProperty(event, 'target', {value: this});
}
const {type} = event;
const listenersOfType = this.listeners[type] || [];
listenersOfType.forEach(listener => listener(event));
}
}
class FakeXMLHttpRequest extends EventTarget {
static DONE = XMLHttpRequest.DONE;
static HEADERS_RECEIVED = XMLHttpRequest.HEADERS_RECEIVED;
static LOADING = XMLHttpRequest.LOADING;
static OPENED = XMLHttpRequest.OPENED;
static UNSENT = XMLHttpRequest.UNSENT;
constructor() {
super();
this._request = new XMLHttpRequest();
Object.defineProperties(this, {
// properties
status: {
get: () => this._request.status
},
statusText: {
get: () => this._request.statusText
},
response: {
get: () => this._request.response
},
responseText: {
get: () => this._request.responseText
},
responseXML: {
get: () => this._request.responseXML
},
readyState: {
get: () => this._request.readyState
},
upload: {
get: () => this._request.upload
},
withCredentials: {
get: () => this._request.withCredentials
},
// Methods
abort: {
get: () => this._request.abort.bind(this._request)
},
overrideMimeType: {
get: () => this._request.overrideMimeType.bind(this._request)
},
setRequestHeader: {
get: () => this._request.setRequestHeader.bind(this._request)
},
getRequestheader: {
get: () => this._request.getAllResponseHeaders.bind(this._request)
},
getAllResponseHeaders: {
get: () => this._request.getAllResponseHeaders.bind(this._request)
},
getAllResponseHeaders: {
get: () => this._request.bind(this._request)
},
send: {
get: () => this._request.send.bind(this._request)
},
// Setters
timeout: {
get: () => this._request.timeout,
set: value => this._request.timeout = value
},
responseType: {
get: () => this._request.responseType,
set: value => this._request.responseType = value
},
onabort: {
get: () => this._request.onabort,
set: value => this._request.onabort = value
},
onerror: {
get: () => this._request.onerror,
set: value => this._request.onerror = value
},
onload: {
get: () => this._request.onload,
set: value => this._request.onload = value
},
onloadend: {
get: () => this._request.onloadend,
set: value => this._request.onloadend = value
},
onloadstart: {
get: () => this._request.onloadstart,
set: value => this._request.onloadstart = value
},
onprogress: {
get: () => this._request.onprogress,
set: value => this._request.onprogress = value
},
onreadystatechange: {
get: () => this._request.onreadystatechange,
set: value => this._request.onreadystatechange = value
},
ontimeout: {
get: () => this._request.ontimeout,
set: value => this._request.ontimeout = value
}
});
// Events
this._request.addEventListener('abort', e => this.dispatchEvent(e));
this._request.addEventListener('error', e => this.dispatchEvent(e));
this._request.addEventListener('load', e => this.dispatchEvent(e));
this._request.addEventListener('loadend', e => this.dispatchEvent(e));
this._request.addEventListener('loadstart', e => this.dispatchEvent(e));
this._request.addEventListener('progress', e => this.dispatchEvent(e));
this._request.addEventListener('readystatechange', e => this.dispatchEvent(e));
this._request.addEventListener('timeout', e => this.dispatchEvent(e));
this._request.addEventListener('load', e => {
console.log(`response: ${this._request.responseType}`);
this.dispatchEvent(e);
});
}
open(method, url) {
console.log(`proxying: ${method} ${url}`);
this._request.open(method, url);
}
}
win.XMLHttpRequest = FakeXMLHttpRequest
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment