From ec85ffa3c1d5acdba92af1707a74fe690ada6b12 Mon Sep 17 00:00:00 2001
From: daief <1437931235@qq.com>
Date: Fri, 11 Dec 2020 13:50:29 +0800
Subject: [PATCH] wip: refine code
---
src/Setting/Root.vue | 19 ++++------
src/common/index.ts | 1 +
src/proxy/fetch.ts | 87 +++++++++++++++++++++++++-----------------
src/proxy/xhr.ts | 90 ++++++++++++++++++++++----------------------
4 files changed, 106 insertions(+), 91 deletions(-)
diff --git a/src/Setting/Root.vue b/src/Setting/Root.vue
index c3262f8..6ea498e 100644
--- a/src/Setting/Root.vue
+++ b/src/Setting/Root.vue
@@ -21,8 +21,9 @@
@@ -49,7 +50,6 @@ export default defineComponent({
onMounted(() => {
state.matchedSetList = Store.getMatchedSetList();
- console.log(state.matchedSetList);
});
watch(
@@ -73,14 +73,11 @@ export default defineComponent({
show.value = false;
},
handleAdd: () => {
- state.matchedSetList = [
- {
- domainTest: location.hostname,
- rules: [],
- id: uuid4(),
- },
- ...state.matchedSetList,
- ];
+ state.matchedSetList.unshift({
+ domainTest: location.hostname,
+ rules: [],
+ id: uuid4(),
+ });
},
handleAddRule: (i: number) => {
state.matchedSetList[i].rules.push({
diff --git a/src/common/index.ts b/src/common/index.ts
index 6df92ae..00b72d1 100644
--- a/src/common/index.ts
+++ b/src/common/index.ts
@@ -5,6 +5,7 @@ export const cache = new WeakMap<
{
method: string;
url: string;
+ [k: string]: any;
}
>();
diff --git a/src/proxy/fetch.ts b/src/proxy/fetch.ts
index 8321b49..442921c 100644
--- a/src/proxy/fetch.ts
+++ b/src/proxy/fetch.ts
@@ -1,63 +1,82 @@
-import { cache, safeParse, vmCtx } from '@/common';
+import { cache, vmCtx } from '@/common';
import { Store } from '@/data';
-const originalFetch = vmCtx.fetch;
-const originalJson = Response.prototype.json;
-const originalText = Response.prototype.text;
-
function proxyRes(response: Response) {
const ruleSet = Store.findCurrentSet();
const matchedRule = ruleSet.rules.find(it =>
response.url.includes(it.apiTest)
);
- const res = matchedRule?.response;
- const payload = cache.get(response);
+ return matchedRule?.response;
+}
- if (res) {
- GM_log(
- `❗️ [fetch] Response is proxyed:\n`,
- `${payload?.method || ''} ${response.url}\n`,
- safeParse(res)
- );
- }
-
- return res;
+function log({ method, url, status, response }: any) {
+ GM_log(`❗️ [fetch] Response is proxyed:\n`);
+ console.table({
+ method,
+ url,
+ status,
+ 'proxyed response': response,
+ });
}
if (typeof Response !== 'undefined') {
+ const nativeFetch = vmCtx.fetch;
+ const nativeJson = Response.prototype.json;
+ const nativeText = Response.prototype.text;
+
Response.prototype.json = async function (this: Response, ...args) {
- const nativeRes = await originalJson.apply(this, args);
- const res = proxyRes(this);
- if (res) {
- try {
- return JSON.parse(res);
- } catch (error) {
- console.warn(
- `❌ Error when parse proxy response for [${this.url}]. Use original result.`
- );
- return nativeRes;
- }
+ const nativeRes = await nativeJson.apply(this, args);
+ const payload = cache.get(this);
+
+ if (payload?.proxyedResponse) {
+ log({
+ method: payload.method,
+ url: this.url,
+ status: this.status,
+ response: payload.proxyedResponse,
+ });
+ return JSON.parse(payload.proxyedResponse);
}
return nativeRes;
};
Response.prototype.text = async function (this: Response, ...args) {
- const nativeRes = await originalText.apply(this, args);
- const res = proxyRes(this);
- if (res) {
- return res;
+ const nativeRes = await nativeText.apply(this, args);
+ const payload = cache.get(this);
+
+ if (payload?.proxyedResponse) {
+ log({
+ method: payload.method,
+ url: this.url,
+ status: this.status,
+ response: payload.proxyedResponse,
+ });
+ return payload.proxyedResponse;
}
+
return nativeRes;
};
- vmCtx.fetch = async function (...args) {
- const res: Response = await originalFetch.apply(this, args);
+ vmCtx.fetch = async function (input: RequestInfo, init?: RequestInit) {
+ let method = 'GET';
+ if (input instanceof Request) {
+ method = input.method;
+ } else {
+ method = init?.method || method;
+ }
+
+ const res: Response = await nativeFetch.apply(this, [input, init]);
+
+ const proxyedResponse = proxyRes(res);
+
cache.set(res, {
- method: args[1]?.method || 'GET',
+ method,
url: res.url,
+ proxyedResponse,
});
+
return res;
};
}
diff --git a/src/proxy/xhr.ts b/src/proxy/xhr.ts
index 8c1e103..404d9f5 100644
--- a/src/proxy/xhr.ts
+++ b/src/proxy/xhr.ts
@@ -1,58 +1,56 @@
-import { cache, safeParse } from '@/common';
+import { vmCtx } from '@/common';
import { Store } from '@/data';
-const originalOpen = XMLHttpRequest.prototype.open;
-const originalSend = XMLHttpRequest.prototype.send;
+const NativeXMLHttpRequest = vmCtx.XMLHttpRequest;
-XMLHttpRequest.prototype.open = function (...args: any[]) {
- cache.set(this, {
- method: args[0],
- url: args[1],
- });
- return originalOpen.apply(this, args);
-};
-
-XMLHttpRequest.prototype.send = function (
- this: XMLHttpRequest,
- ...args: any[]
+vmCtx.XMLHttpRequest = class extends (
+ NativeXMLHttpRequest
) {
- this.addEventListener(
- 'readystatechange',
- function () {
- const payload = cache.get(this);
+ #mockResponse: string;
+ #url: string;
+ #method: string;
+ #proxyed: boolean = false;
- if (!payload) {
- return;
- }
+ constructor() {
+ super();
- const ruleSet = Store.findCurrentSet();
- const matchedRule = ruleSet.rules.find(it =>
- payload.url.includes(it.apiTest)
- );
+ ['load', 'error'].forEach(ev => {
+ this.addEventListener(ev, () => {
+ if (!this.#proxyed) return;
- if (matchedRule?.response && this.readyState === 3) {
- Object.defineProperty(this, 'response', {
- writable: true,
- });
- Object.defineProperty(this, 'responseText', {
- writable: true,
+ GM_log(`❗️ [XHR] Response is proxyed:\n`);
+ console.table({
+ method: this.#method,
+ url: this.#url,
+ status: this.status,
+ 'proxyed response': this.#mockResponse,
});
+ });
+ });
+ }
- // @ts-ignore
- this.response = matchedRule.response;
- // @ts-ignore
- this.responseText = matchedRule.response;
+ get response() {
+ return this.#mockResponse || super.response;
+ }
- GM_log(
- `❗️ [XHR] Response is proxyed:\n`,
- `${payload.method} ${payload.url}\n`,
- safeParse(matchedRule.response)
- );
- }
- },
- {
- capture: true,
+ get responseText() {
+ return this.#mockResponse || super.responseText;
+ }
+
+ open(method: string, url: string): void {
+ this.#method = method;
+ this.#url = url;
+
+ const ruleSet = Store.findCurrentSet();
+ const matchedRule = ruleSet.rules.find(it =>
+ this.#url.includes(it.apiTest)
+ );
+
+ if (matchedRule?.response) {
+ this.#mockResponse = matchedRule.response;
+ this.#proxyed = true;
}
- );
- return originalSend.apply(this, args);
+
+ return super.open(method, url);
+ }
};