美文网首页
Electron获取webview中ajax请求内容的方法

Electron获取webview中ajax请求内容的方法

作者: 二进制焰火 | 来源:发表于2019-01-15 21:17 被阅读0次

Electron中,可以通过WebRequest监听webview中请求的各个阶段,并且获取或修改请求头和响应头。

但却没有提供获取请求内容的方法。那么如何获取请求内容呢?

首先,我们可以通过比较暴力的方法,就是在webRequest.onCompleted时,重新利用如http模块,对url再发送一次请求,从而获取请求内容。

但这个方法也有弊端,那就是,某些ajax请求,是不能重复的,尤其是POST请求。

比如一个点赞功能,第一次请求服务端会返回成功。第二次再请求,服务端就会报错了。

那么如何做才能直接获取到ajax请求的内容呢?

接下来,我教大家一种方法,就是

利用webview的preload功能,劫持原生XHRHttpRequest类,来实现在Electron中获取ajax请求内容

原理是,Electron的webview标签,有个preload属性,可以在页面加载之前,注入指定的js脚本,并且这个js脚本是一定集成了node环境的。

那么我们就可以在这个脚本中,将原生的XHRHttpRequest类替换掉。每当页面中通过XHRHttpRequest发送ajax请求是,我们就可以先拿到内容,再返回给页面了。废话不多说,直接上代码

代码基于ES6 

const READY_STATE_CHANGE = 'readystatechange';

let gHandlerList = [],//截获请求的处理函数列表

    gIsInited = false;//是否已经初始化

let T_RSC_HANDLERS = Symbol('readyStateChangeHandler');

let initProxy = function(){

    if(gIsInited)return;

    gIsInited = true;

    //这里先缓存一份原生的XMLHttpRequest类

    let winXMLHttpRequest = window.XMLHttpRequest;

    //用于替换原生XMLHttpRequest的类,继承自XMLHttpRequest

    let ProxyXHR = class extends winXMLHttpRequest{

        constructor(){

            super(...arguments);

            //readystatechange

            //数组中第0个为页面中调用xhr.onreadystatechange的回调函数

            //其他的为页面中调用addEventListener('readystatechange')时的回调函数

            this[T_RSC_HANDLERS] = [null];

            //调用原生XMLHttpRequest的addEventListener,添加对readystatechange事件的监听

            super.addEventListener(READY_STATE_CHANGE,async ()=>{

                if(this.readyState == 4 && gHandlerList.length){//只有4的时候会回调proxyHandler

                    try{

                        //调用注册的handler

                        await gHandlerList.map(proxyHandler => proxyHandler.call(this,this));

                    }

                    catch(e){

                        //TODO 这里可以替换为其他的错误处理逻辑

                        console.error(e);

                    }

                }

                //调用页面中注册的回调函数,保证页面中逻辑正常

                this[T_RSC_HANDLERS].forEach(handler => handler && handler.apply(this,arguments));

            });

        }

        /**

        * 重写addEventListener函数,对readystatechange事件做特殊处理

        */

        addEventListener(type,handler){

            if(type == READY_STATE_CHANGE){

                this[T_RSC_HANDLERS].push(handler);

            }

            else{

                return super.addEventListener(...arguments);

            }

        }

        /**

        * 重写removeEventListener函数,对readystatechange事件做特殊处理

        */

        removeEventListener(type,handler){

            if(type == READY_STATE_CHANGE){

                this[T_RSC_HANDLERS] = this[T_RSC_HANDLERS].filter(i => i!== handler);

            }

            else{

                return super.removeEventListener(...arguments);

            }

        }

        /**

        * 重写onreadystatechange属性的setter

        */

        set onreadystatechange(val){

            this[T_RSC_HANDLERS][0] = val;

        }

        /**

        * 重写onreadystatechange属性的getter

        */

        get onreadystatechange(){

            return this[T_RSC_HANDLERS][0] || null;

        }

    }

    //覆盖原生的XMLHttpRequest

    window.XMLHttpRequest = ProxyXHR;

}

/**

* 增加一个handler

* 当xhr.readyState == 4时,回调handler,handler中,可以通过xhr.responseText获取请求返回内容

* @param {function} handler function(xhr){}

*/

let addHandler = function(handler){

    initProxy();

    gHandlerList.push(handler);

}

/**

* 移除指定的handler

* @param {function} handler 调用addHandler时添加的handler

*/

let removeHandler = function(handler){

    gHandlerList = gHandlerList.filter(h => h!== handler);

}

module.exports.addHandler = addHandler;

module.exports.removeHandler = removeHandler;

剩下的业务代码就简单了,获取到xhr后,简单处理,通过ipcRenderer.sendToHost即可将xhr内容发送到BrowserWindow中

/**

* preload.js

*/

const xhrProxy = require('./xhr_proxy.js');

const {ipcRenderer} = require('electron');

xhrProxy.addHandler(function(xhr){

    let data = {};

    //TODO 具体业务代码

    //通过ipcRenderer.sendToHost即可将xhr内容发送到BrowserWindow中

    ipcRenderer.sendToHost('channel',data);

});

相关文章

  • Electron获取webview中ajax请求内容的方法

    Electron中,可以通过WebRequest监听webview中请求的各个阶段,并且获取或修改请求头和响应头。...

  • WebView详解

    一. WebView的基础用法 创建WebView: WebView的代理方法: 二. 获取WebView内容高度...

  • Python爬虫——Python 岗位分析报告

    本篇以拉勾网为例来说明一下如何获取 Ajax 请求内容 本文目标 获取 Ajax 请求,解析 JSON 中所需字段...

  • Python爬虫——Python岗位分析报告

    本篇以拉勾网为例来说明一下如何获取 Ajax 请求内容 本文目标 1. 获取 Ajax 请求,解析 JSON 中所...

  • jQuery

    jQuery语法: jQuery获取内容和属性 : AJAX load()方法: jQuery ajax() 方法...

  • React-Electron-Webview-获取内容

    如何在其他元素内获取webview载入的guest内容? 问题点在于: 在主进程中如何获得渲染进程中的内容 web...

  • 原生ajax和jquery中的ajax

    原生的ajax请求方法: jquery中的ajax:

  • js解析xml

    案例:ajax请求获取的数据为xml文件,解析xml标签中的数据信息 1、ajax请求,测试地址为:获取地图坐标偏...

  • 使用promise封装ajax请求

    封装一个ajax请求方法: 调用ajax方法,发送请求

  • 爬虫4

    请求方式:get 和 post 获取AJAX加载的内容 --用post,把数据存储在request请求里的data...

网友评论

      本文标题:Electron获取webview中ajax请求内容的方法

      本文链接:https://www.haomeiwen.com/subject/qssudqtx.html