UNPKG

@ng1005/chrome-extension-common

Version:

chrome扩展通用库--消息与storage

332 lines (323 loc) 11.6 kB
export const listenerKey='_ajaxProxyInstance_listener_' export const receiveKey='_ajaxProxyInstance_receive_' export const script=` const _ajaxProxyInstance = { oriXhr: window.XMLHttpRequest, oriFetch: window.fetch.bind(window), listenerKey:'_ajaxProxyInstance_listener_', receiveKey:'_ajaxProxyInstance_receive_', interceptor:{ request:{handler:[],use:(func)=>{if (func && typeof func === 'function'){_ajaxProxyInstance.interceptor.request.handler.push(func)}}}, response:{handler:[],use:(func)=>{if (func && typeof func === 'function'){_ajaxProxyInstance.interceptor.response.handler.push(func)}}} }, xhr: function () { const isObjectOrArray=(source)=>{ var type = Object.prototype.toString.call(source); var res = type === '[object Array]' || type === '[object Object]'; return res; } //转换为json const toJson=(str)=>{ let json=str try{ json=JSON.parse(str) }catch(e){ } return json } //请求参数 let req={url:'',method:'GET',headers:{},data:{}} const xhr = new _ajaxProxyInstance.oriXhr; const handler=_ajaxProxyInstance.interceptor.request.handler const processHandler=()=>{ for (let i = 0; i < handler.length; ++i) { req=handler[i].call(this, req,_ajaxProxyInstance.xhr) } return req; } const oriXhr = new _ajaxProxyInstance.oriXhr; for (const property in oriXhr) { if (property === 'onreadystatechange') { oriXhr.onreadystatechange = (...args) => { // 下载成功 if (this.readyState === 4) { // console.log('ajax response----',req.url,xhr.responseText) //axios请求参数---需要重写的参数 let options={ url:req.url, method:req.method, data:req.data, headers:req.headers, status: xhr.status, statusText: '', response:xhr.response, responseHeaders: xhr.responseHeaders,//响应时返回响应header } if (xhr.status === 200&&xhr.responseText){// 判断是否有success方法并执行 const resContentType=xhr.getResponseHeader("Content-Type") if(resContentType.includes('application/json')){ //将json字符串转换为json对象 options.response=toJson(xhr.responseText) } } //拦截处理 let handlers=_ajaxProxyInstance.interceptor.response.handler for(let i=0;i<handlers.length;i++){ options=handlers[i].call(this, options,_ajaxProxyInstance.xhr) } //重写结果 xhr.responseText=isObjectOrArray(options.response)?JSON.stringify(options.response):options.response xhr.response=isObjectOrArray(options.response)?JSON.stringify(options.response):options.response } this.onreadystatechange && this.onreadystatechange.apply(this, args); } this.onreadystatechange = null; continue; } else if (property === 'onload') { } else if (property === 'open') { this.open = (...args) => { const [method, url] = args; req.url=url req.method=method //处理拦截器 req=processHandler() //重写请求 args[0]=req.method args[1]=req.url oriXhr.open && oriXhr.open.apply(oriXhr, args); } continue; } else if (property === 'setRequestHeader') { this.setRequestHeader = (...args) => { let header={[args[0]]: args[1]} req.headers=Object.assign(req.headers,header) //处理拦截器 req=processHandler() //重写请求---默认最后一个加入的key为当前key let keys=Object.keys(req.headers) args[0]=keys[keys.length-1] args[1]=req.headers[args[0]] oriXhr.setRequestHeader && oriXhr.setRequestHeader.apply(oriXhr, args); } continue; } else if (property === 'send') { this.send = (...args) => { //发送数据 if(!['get','put',''].includes(req.method.toLocaleLowerCase())){ let body=args[0] req.data=body&&isObjectOrArray(body)?body:toJson(body) //处理拦截器 req=processHandler() //重写请求---数据 args[0]=req.data||arg[0] } oriXhr.send && oriXhr.send.apply(oriXhr, args); } continue; } if (typeof oriXhr[property] === 'function') { this[property] = oriXhr[property].bind(oriXhr); } else { // responseText和response不是writeable的,但拦截时需要修改它,所以修改就存储在this[\``+'_${property}'+`\`]上 if (['responseText', 'response', 'status'].includes(property)) { Object.defineProperty(this, property, { get: () => this[\``+'_${property}'+`\`] == undefined ? oriXhr[property] : this[\``+'_${property}'+`\`], set: (val) => this[\``+'_${property}'+`\`] = val, enumerable: true }); } else { Object.defineProperty(this, property, { get: () => oriXhr[property], set: (val) => oriXhr[property] = val, enumerable: true }); } } } }, fetch: function (...args) { const isObjectOrArray=(source)=>{ var type = Object.prototype.toString.call(source); var res = type === '[object Array]' || type === '[object Object]'; return res; } //转换为json const toJson=(str)=>{ let json=str try{ json=JSON.parse(str) }catch(e){ } return json } let [url,opts]=args let req={ url, method:opts?.method, data:!opts?.body||isObjectOrArray(opts?.body)?opts?.body:toJson(opts?.body), headers:opts?.headers, } const processHandler=(handler,...args)=>{ for (let i = 0; i < handler.length; ++i) { req=handler[i].call(this, req,_ajaxProxyInstance.fetch) } args[0]=req.url||args[0] if(!opts){ opts={} } opts['method']=req.method||opts?.method opts['body']=req.data||opts?.body opts['body']=isObjectOrArray(opts['body'])?JSON.stringify(opts['body']):opts['body'] opts['headers']=req.headers||opts?.headers args[1]=opts; return args } const getBody = async (stream) => { let text = ''; const decoder = new TextDecoder('utf-8'); const reader = stream.getReader(); const processData = (result) => { if (result.done) { return text; } const value = result.value; // Uint8Array text += decoder.decode(value, {stream: true}); // 读取下一个文件片段,重复处理步骤 return reader.read().then(processData); }; return await reader.read().then(processData); } args=processHandler(_ajaxProxyInstance.interceptor.request.handler,...args) return _ajaxProxyInstance.oriFetch(...args).then(async (response) => { let handler=_ajaxProxyInstance.interceptor.response.handler if(handler.length>0){ //默认body都返回json let body=await getBody(response.body) body=isObjectOrArray(body)?body:toJson(body) //axios请求参数---需要重写的参数 let options={ url, method:req?.method||'GET', data:req?.data||{}, headers:req?.headers||{}, status: response.status, statusText: response.statusText, response:body, responseHeaders: response.headers||opts.headers,//响应时返回响应header } // console.log('ajax fetch response----',options.url) //重写返回状态与返回文本/json for (let i = 0; i < handler.length; ++i) { options=handler[i].call(this, options,response,_ajaxProxyInstance.fetch) } //重新组装成Response let streamBody=isObjectOrArray(options.response)?JSON.stringify(options.response):options.response const stream = new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode(streamBody)); controller.close(); } }); const newResponse = new Response(stream, { headers: options.headers||response.headers, status: options.status||response.status, statusText: options.statusText||response.statusText, }); //生成代理对象 const responseProxy = new Proxy(newResponse, { get: function (target, name) { switch (name) { case 'body': case 'bodyUsed': case 'ok': case 'redirected': case 'type': case 'url': return response[name]; } return target[name]; } }); for (let key in responseProxy) { if (typeof responseProxy[key] === 'function') { responseProxy[key] = responseProxy[key].bind(newResponse); } } return responseProxy; }else{ return response } }) } } //添加拦截器及监听window message---调用一次 const _initAjaxProxyInstanceInterceptor=()=>{ window._ajaxProxyInstance=_ajaxProxyInstance window._getAjaxList=(str)=>{ let list=[] ajaxList.forEach(r=>{ if(r.url.indexOf(str)>-1||!str){ list.push(r) } }) return list } const toJson=(json)=>{return JSON.parse(JSON.stringify(json))} let ajaxList=[]//所有ajax请求 _ajaxProxyInstance.interceptor.response.use((req,response,fetch)=>{ ajaxList.push(Object.assign({},req)) return req }) let onRequestFlag=false; const onRequest=()=>{ if(!onRequestFlag){ _ajaxProxyInstance.interceptor.request.use((req,response,fetch)=>{ window.postMessage({key:_ajaxProxyInstance.receiveKey,act:'onRequest',params:toJson(req)}, '*') return req }) onRequestFlag=true; } } let onResponseFlag=false; const onResponse=()=>{ if(!onRequestFlag){ _ajaxProxyInstance.interceptor.request.use((req,response,fetch)=>{ window.postMessage({key:_ajaxProxyInstance.receiveKey,act:'onResponse',params:toJson(req)}, '*') return req }) onResponseFlag=true; } } window.addEventListener('message', function (e) { // 监听 message 事件 const {origin='*',data={}}=e //监听处理ajax const {key='',act='getList',params={}}=data; if(key==_ajaxProxyInstance.listenerKey){ switch(act){ case 'getList': window.postMessage({key:_ajaxProxyInstance.receiveKey,act,params:toJson(ajaxList)}, '*') break; case 'onRequest': onRequest() break; case 'onResponse': onResponse() break; default://可以进行扩展如:扩展通过filter与req来覆盖请求 break; } } }); } _initAjaxProxyInstanceInterceptor() const _initAjaxProxyInstance=()=>{ for (const k in _ajaxProxyInstance.oriXhr) { _ajaxProxyInstance.xhr[k] = _ajaxProxyInstance.oriXhr[k] } window.XMLHttpRequest = _ajaxProxyInstance.xhr; window.fetch = _ajaxProxyInstance.fetch; } window.addEventListener("message", function (event) { _initAjaxProxyInstance() }, false); `