From 39777aa84fddacffa09ed8839d4058cf3da2e7d9 Mon Sep 17 00:00:00 2001 From: daief <1437931235@qq.com> Date: Mon, 30 Nov 2020 12:29:51 +0800 Subject: [PATCH] wip: proxy fetch --- src/@types/global.d.ts | 2 ++ src/common/index.ts | 5 +++- src/global.less | 1 + src/index.ts | 12 +++++---- src/proxy/fetch.ts | 58 ++++++++++++++++++++++++++++++++++++++++++ src/proxy/xhr.ts | 2 +- 6 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 src/proxy/fetch.ts diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 9a05d90..709d57a 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -11,3 +11,5 @@ declare function GM_log(...msg: any[]): void; declare function GM_setValue(name: string, value: any): void; declare function GM_addStyle(css: string): void; declare function GM_getValue(name: string, defaultValue?: any): any; + +declare const unsafeWindow: Window & typeof globalThis; diff --git a/src/common/index.ts b/src/common/index.ts index 6d2fa81..aa40093 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -1,7 +1,7 @@ export * from './utils'; export const cache = new WeakMap< - XMLHttpRequest, + XMLHttpRequest | Response, { method: string; url: string; @@ -9,3 +9,6 @@ export const cache = new WeakMap< >(); export const NAMESPACE = location.host; + +export const vmCtx: Window & typeof globalThis = + typeof unsafeWindow !== 'undefined' ? unsafeWindow : window; diff --git a/src/global.less b/src/global.less index 7c99158..15ef0da 100644 --- a/src/global.less +++ b/src/global.less @@ -9,6 +9,7 @@ background-color: #6cf; opacity: 0.5; transition: opacity 0.3s; + box-shadow: 0 0 10px 0px rgb(0 0 0 / 35%); &:hover { opacity: 1; diff --git a/src/index.ts b/src/index.ts index 64f19cf..2a24662 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,7 @@ +import './proxy/fetch'; import './proxy/xhr'; import './global.less'; +import { vmCtx } from './common'; // TODO change to async import { render } from './SettingPanel'; @@ -12,7 +14,7 @@ let tX = 0; let tY = 0; let elRect: DOMRect | null = null; -window.addEventListener('DOMContentLoaded', () => { +vmCtx.addEventListener('DOMContentLoaded', () => { const el = document.createElement('div'); el.innerText = '设置'; el.className = 'response-proxy-page-root-fixed-button'; @@ -39,7 +41,7 @@ window.addEventListener('DOMContentLoaded', () => { tY = e.clientY - elRect.top; }); - window.addEventListener('mouseup', async e => { + vmCtx.addEventListener('mouseup', async e => { isDrag = false; if (isMove) { isMove = false; @@ -51,7 +53,7 @@ window.addEventListener('DOMContentLoaded', () => { } }); - window.addEventListener('mousemove', e => { + vmCtx.addEventListener('mousemove', e => { isMove = true; if (!isDrag) { return; @@ -60,11 +62,11 @@ window.addEventListener('DOMContentLoaded', () => { e.preventDefault(); let left = e.clientX - tX; - left = Math.min(left, window.innerWidth - elRect!.width); + left = Math.min(left, vmCtx.innerWidth - elRect!.width); left = Math.max(left, 0); let top = e.clientY - tY; - top = Math.min(top, window.innerHeight - elRect!.height); + top = Math.min(top, vmCtx.innerHeight - elRect!.height); top = Math.max(top, 0); el.style.left = left + 'px'; diff --git a/src/proxy/fetch.ts b/src/proxy/fetch.ts new file mode 100644 index 0000000..10d7b02 --- /dev/null +++ b/src/proxy/fetch.ts @@ -0,0 +1,58 @@ +import { cache, safeParse, 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); + + if (res) { + GM_log( + `❗️ Response is proxyed:\n`, + `${payload?.method || ''} ${response.url}\n`, + safeParse(res) + ); + } + + return res; +} + +if (typeof Response !== 'undefined') { + 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) { + 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; + } + return nativeRes; + }; + + vmCtx.fetch = async function (...args) { + const res: Response = await originalFetch.apply(this, args); + cache.set(res, { + method: args[1]?.method || 'GET', + url: res.url, + }); + return res; + }; +} diff --git a/src/proxy/xhr.ts b/src/proxy/xhr.ts index 16bc8fa..4752881 100644 --- a/src/proxy/xhr.ts +++ b/src/proxy/xhr.ts @@ -30,7 +30,7 @@ XMLHttpRequest.prototype.send = function ( payload.url.includes(it.apiTest) ); - if (matchedRule && matchedRule.response && this.readyState === 3) { + if (matchedRule?.response && this.readyState === 3) { Object.defineProperty(this, 'response', { writable: true, });