Refactor XHR interceptor
In preparation for future work on the XHR interceptor.
Bug: twpowertools:153
Change-Id: Id8df1486c033ba02429a17d161e2bcc87a0f1de5
diff --git a/src/injections/xhrInterceptor.js b/src/injections/xhrInterceptor.js
index 071daf5..ef2efe3 100644
--- a/src/injections/xhrInterceptor.js
+++ b/src/injections/xhrInterceptor.js
@@ -1,5 +1,5 @@
import {correctArrayKeys} from '../common/protojs';
-import * as utils from '../common/xhrInterceptorUtils.js';
+import * as utils from '../xhrInterceptor/utils.js';
const originalOpen = window.XMLHttpRequest.prototype.open;
const originalSetRequestHeader =
@@ -8,60 +8,121 @@
let messageID = 0;
-window.XMLHttpRequest.prototype.open = function() {
- this.$TWPTRequestURL = arguments[1] || location.href;
- this.$TWPTID = messageID++;
+class XHRProxy {
+ constructor() {
+ this.originalXMLHttpRequest = window.XMLHttpRequest;
+ const originalXMLHttpRequest = this.originalXMLHttpRequest;
- let interceptors = utils.matchInterceptors('response', this.$TWPTRequestURL);
- if (interceptors.length > 0) {
- this.addEventListener('load', function() {
- var body = utils.getResponseJSON(this);
- if (body !== undefined)
- interceptors.forEach(i => {
- utils.triggerEvent(i.eventName, body, this.$TWPTID);
- });
+ this.messageID = 0;
+
+ window.XMLHttpRequest = function() {
+ this.xhr = new originalXMLHttpRequest();
+ this.$TWPTID = messageID++;
+ };
+
+ const methods = [
+ 'open', 'abort', 'setRequestHeader', 'send', 'addEventListener',
+ 'removeEventListener', 'getResponseHeader', 'getAllResponseHeaders',
+ 'dispatchEvent', 'overrideMimeType'
+ ];
+ methods.forEach(method => {
+ window.XMLHttpRequest.prototype[method] = function() {
+ const proxyThis = this;
+
+ switch (method) {
+ case 'open':
+ this.$TWPTRequestURL = arguments[1] || location.href;
+
+ var interceptors =
+ utils.matchInterceptors('response', this.$TWPTRequestURL);
+ if (interceptors.length > 0) {
+ this.xhr.addEventListener('load', function() {
+ var body = utils.getResponseJSON(this);
+ if (body !== undefined)
+ interceptors.forEach(i => {
+ utils.triggerEvent(i.eventName, body, proxyThis.$TWPTID);
+ });
+ });
+ }
+ break;
+
+ case 'setRequestHeader':
+ let header = arguments[0];
+ let value = arguments[1];
+ if ('Content-Type'.localeCompare(
+ header, undefined, {sensitivity: 'accent'}) == 0)
+ this.$isArrayProto = (value == 'application/json+protobuf');
+ break;
+
+ case 'send':
+ var interceptors = utils.matchInterceptors(
+ 'request', this.$TWPTRequestURL || location.href);
+ if (interceptors.length > 0) {
+ let rawBody = arguments[0];
+ let body;
+ if (typeof (rawBody) === 'object' &&
+ (rawBody instanceof Object.getPrototypeOf(Uint8Array))) {
+ let dec = new TextDecoder('utf-8');
+ body = dec.decode(rawBody);
+ } else if (typeof (rawBody) === 'string') {
+ body = rawBody;
+ } else {
+ console.error(
+ 'Unexpected type of request body (' + typeof (rawBody) +
+ ').',
+ this.$TWPTRequestURL);
+ return;
+ }
+
+ let JSONBody = JSON.parse(body);
+ if (this.$isArrayProto) JSONBody = correctArrayKeys(JSONBody);
+
+ interceptors.forEach(i => {
+ utils.triggerEvent(i.eventName, JSONBody, this.$TWPTID);
+ });
+ }
+ break;
+ }
+ return this.xhr[method].apply(this.xhr, arguments);
+ };
});
- }
- originalOpen.apply(this, arguments);
-};
-
-window.XMLHttpRequest.prototype.setRequestHeader = function() {
- originalSetRequestHeader.apply(this, arguments);
-
- let header = arguments[0];
- let value = arguments[1];
- if ('Content-Type'.localeCompare(
- header, undefined, {sensitivity: 'accent'}) == 0)
- this.$isArrayProto = (value == 'application/json+protobuf');
-};
-
-window.XMLHttpRequest.prototype.send = function() {
- originalSend.apply(this, arguments);
-
- let interceptors =
- utils.matchInterceptors('request', this.$TWPTRequestURL || location.href);
- if (interceptors.length > 0) {
- let rawBody = arguments[0];
- let body;
- if (typeof (rawBody) === 'object' &&
- (rawBody instanceof Object.getPrototypeOf(Uint8Array))) {
- let dec = new TextDecoder('utf-8');
- body = dec.decode(rawBody);
- } else if (typeof (rawBody) === 'string') {
- body = rawBody;
- } else {
- console.error(
- 'Unexpected type of request body (' + typeof (rawBody) + ').',
- this.$TWPTRequestURL);
- return;
- }
-
- let JSONBody = JSON.parse(body);
- if (this.$isArrayProto) JSONBody = correctArrayKeys(JSONBody);
-
- interceptors.forEach(i => {
- utils.triggerEvent(i.eventName, JSONBody, this.$TWPTID);
+ const scalars = [
+ 'onabort',
+ 'onerror',
+ 'onload',
+ 'onloadstart',
+ 'onloadend',
+ 'onprogress',
+ 'onreadystatechange',
+ 'readyState',
+ 'response',
+ 'responseText',
+ 'responseType',
+ 'responseXML',
+ 'status',
+ 'statusText',
+ 'upload',
+ 'withCredentials',
+ 'DONE',
+ 'UNSENT',
+ 'HEADERS_RECEIVED',
+ 'LOADING',
+ 'OPENED'
+ ];
+ scalars.forEach(scalar => {
+ Object.defineProperty(window.XMLHttpRequest.prototype, scalar, {
+ get: function() {
+ return this.xhr[scalar];
+ },
+ set: function(val) {
+ this.xhr[scalar] = val;
+ },
+ });
});
+
+ return this;
}
-};
+}
+
+new XHRProxy();