注册 登录
编程论坛 VFP论坛

请教吹版 在 VFP WEBVIEW2 能直接运行devtools 里的XHR吗?

SATANA 发布于 2024-10-30 14:01, 332 次点击
在 VFP WEBVIEW2 在不独立打开devtools的情况下, 能否直接运行devtools 里的XHR吗 比如利用WEBVIEW2 的实现XHR提交,XHR的重播,并获取返回值,比如获取xmlhttp.responseText
谢谢

[此贴子已经被作者于2024-11-1 04:27编辑过]

9 回复
#2
yiyanxiyin2024-11-01 09:45
你这是要开发浏览器插件还是仅仅想模拟某个网站的xhr请求获取response?

要在webview2中实现重播xhr, 调用devtools好像不可能, devtools没有接口供调用, 可以考虑再webview2中注入js重写xmlhttprequest的open和send方法, 实现请求头和响应内容的拦截,  将请求头保存起来即可重播, 甚至还能实现修改头再重发
webview2中可能会有安全限制, 上面的方法能否行得通需要测试,如果不行那就终极大法,直接从webview2的源码下手, 修改源码这样才能操控一切




[此贴子已经被作者于2024-11-1 10:55编辑过]

#3
iswith2024-11-01 11:09
逻辑为:将请求结构保存到数组或表,把你的需求对应一行数组或表,把需要更改的地方,利用Webview2的下述两种方案即可完成需求:
*-- WebView2 控件允许你与网络请求交互和修改网络请求,方法有两种:
*方法一:WebResourceResponseReceived 事件提供响应或修改网络请求WebResourceRequested。
*方法二:使用 NavigateWithWebResourceRequest API导航特定的网络请求      

*-- 术语定义:
*拦截:    主机应用可以截获从 WebView2 控件发送到 HTTP 服务器的请求、读取或修改请求,然后将未更改或修改的请求发送到 HTTP 服务器 (或本地代码,而不是 HTTP 服务器) 。
*覆盖:    主机应用可以重写从 HTTP 服务器发送到 WebView2 控件的响应,并将自定义响应发送到 WebView2 控件,而不是原始响应。
*注意: 对于具有虚拟主机名的 URL,不支持使用 WebResourceRequested 事件。 这是因为 WebResourceRequested 不会为 SetVirtualHostNameToFolderMapping 方法触发事件。

*-- 主机应用、WebView2 控件和 HTTP 服务器的交互方式
*WebView2 控件位于主机应用和 HTTP 服务器之间。 当主机应用导航到 URI 时,WebView2 控件会向 HTTP 服务器发送请求。 然后,HTTP 服务器将响应发送到 WebView2 控件。

*-- 截获请求,以监视或修改请求
*主机应用可以 截获 从 WebView2 控件发送到 HTTP 服务器的请求、读取或修改请求,然后将未更改或修改的请求发送到 HTTP 服务器 (或本地代码,而不是 HTTP 服务器) 。
*通过截获请求,可以自定义标头内容、URL 或 GET/POST 方法。 主机应用可能需要截获请求,以在请求中提供可选 POST 内容。

*-- 主机应用可以使用以下 “类” 更改请求的属性
*CoreWebView2WebResourceRequest 类

*-- 标头可以执行的操作
*HTTP 标头提供有关请求或响应的重要信息和元数据。 通过更改 标头 ,可以在网络上执行强大的操作。
*请求标头可用于指示响应 (的格式,例如Accept-*) 标头、设置身份验证令牌、读取和写入 cookie (敏感信息) 、修改用户代理等。 响应标头可用于提供更多响应上下文

*-- 为何要截获从 WebView2 发送的请求?
*通过拦截从 WebView2 发送的请求,可以进一步配置请求。 主机应用可能希望提供可选内容,作为 WebView2 控件自己不知道的请求的一部分。 某些方案包括:
*你正在登录到页面,并且应用具有凭据,因此应用可以提供身份验证标头,而无需用户输入这些凭据。
*你需要应用中的脱机功能,以便在未检测到 Internet 连接时将 URL 重定向到本地文件路径。
*你想要通过 POST 请求将本地文件内容上传到请求服务器

*-- 修改请求的顺序
*1.主机应用设置 WebResourceRequested 筛选器。
*3.主机应用定义 和 WebResourceResponseReceived的WebResourceRequested事件处理程序。
*4.主机应用将 WebView2 控件导航到网页。
*5.WebView2 控件为网页所需的资源创建请求。
*6.WebView2 控件将 WebResourceRequested 事件触发到主机应用。
*7.主机应用侦听并处理 WebResourceRequested 事件。
*8.此时,主机应用可以修改标头。 主机应用还可以延迟 WebResourceRequested 事件,这意味着主机应用会要求更多时间来决定要执行的操作。
*9.WebView2 网络堆栈可以添加更多标头 (例如,可以) 添加 Cookie 和授权标头。
*10.WebView2 控件将请求发送到 HTTP 服务器。
*11.HTTP 服务器将响应发送到 WebView2 控件。
*12.WebView2 控件触发事件 WebResourceResponseReceived 。
*13.主机应用侦听 WebResourceResponseReceived 并处理事件。

* -- “CoreWebView2WebResourceRequest“类
*方法:CreateWebResourceRequest 参数说明:
 *CoreWebView2WebResourceRequest中的标头覆盖WebView2运行时添加的标头,Cookie标头除外。
 *方法只能是GET或POST。仅当方法为post且uri方案为HTTP(S)时,才会发送提供的post数据。
      
*uri      String  摘要:The request URI.
*Method   String  摘要:The HTTP request method.
*postData Stream  摘要:使用CreateStream()
*Headers  String  摘要:The raw request header string delimited by CRLF (optional in last header).


Local uri        ;
    , HttpMethod;
    , postData     ;
    , loStream     ;
    , Headers    ;
    , loRequest   

uri            = [https://bbs.bccn.net/forum-22-1.html]
HttpMethod  = [GET]
postData    = [input=Hello]&&&&formhash=5a44e3df&cookietime=2592000&loginfield=username&username=iswith&password=*0720zhz]
m.loStream  = Thisform.WebView2.CreateStream( m.postData ) &&GetStream 将字符设置成为流类对象(这个比VFP纯字符串,性能要强,默认为UTF8)
Headers     = [Content-Type:text/html; charset=gbk]
m.loRequest = ThisForm.Webview2.CreateWebResourceRequest( m.uri, m.HttpMethod, m.loStream , m.Headers )

只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2024-11-1 11:19编辑过]

#4
iswith2024-11-01 11:39
以下是引用yiyanxiyin在2024-11-1 09:45:51的发言:

你这是要开发浏览器插件还是仅仅想模拟某个网站的xhr请求获取response?

要在webview2中实现重播xhr, 调用devtools好像不可能, devtools没有接口供调用, 可以考虑再webview2中注入js重写xmlhttprequest的open和send方法, 实现请求头和响应内容的拦截,  将请求头保存起来即可重播, 甚至还能实现修改头再重发
webview2中可能会有安全限制, 上面的方法能否行得通需要测试,如果不行那就终极大法,直接从webview2的源码下手, 修改源码这样才能操控一切


你确定要重写一个跟chorme一样的核心,MS没有做到,比较期待。。。
#5
SATANA2024-11-01 11:48
谢谢  iswith
哪怎样获取 js的返回值呢?
比如
if (xhr.readyState == 4){
    if (xhr.status == 200){
      console.log(xhr.responseText);
    } else {
      console.error(xhr.statusText);
    }
怎样获取xhr.responseText的值 给VFP?

[此贴子已经被作者于2024-11-1 16:15编辑过]

#6
yiyanxiyin2024-11-01 17:40
如果要深入webview2调用devtools, 可以研究一下devtools协议,webview2对其进行了封装

同时ms针对.net开发了devtools协议扩展包, 可以看看这个例子 https://learn.   直接串改你的地理位置


#7
iswith2024-11-02 10:02
*确保xhr.responseText是string,注意编码
*--其实我的版本WebView2已经有调试工具的“网络”请求与响应获取模块!
*--事件“OnDevToolsProtocolEventReceive”
*--访问任何页面时,即可获取当前 所有请求(isDevToolsRequest=.T.,cStyle ="request" )/请求响应(isDevToolsResponse=.T.,cStyle ="response" ),脚本



在Webview2注入Com 对象_VfP
*---VFP代码
public responseText
_vfp.setvar( "responseText" , "" )

*-- JS
if (xhr.readyState == 4){
    if (xhr.status == 200){
      _vfp.setvar( "responseText" , xhr.responseText );
    } else {
      console.error(xhr.statusText);
    }

或者
函数jsa  return xhr.responseText
ExecuteScriptasync(jsa) 事件“OnExecuteScriptasync”

[此贴子已经被作者于2024-11-2 10:21编辑过]

#8
SATANA2024-11-03 14:03
iswith老师好 _vfp.setvar  这个函数 是不是还有另外的执行程序?


函数jsa  return xhr.responseText
ExecuteScriptasync(jsa) 事件“OnExecuteScriptasync”
    我没看明白  能否详细点

谢谢老师
#9
iswith2024-11-03 15:23
在Webview2注入Com 对象_VfP:
ThisForm.WebView2.AddHostObjectToScript( 'vfp' , _vfp )
#10
SATANA2024-11-04 03:11
谢谢iswith 以上的基本明白流程了
还有个问题 VFP的变量 怎样让JS利用上
比如
js:
xhr.send('username=VFPsata11&password=VFP9090901&f_superauth=VFP546576&dummy=Super+Auth+Code&loginform=1');
其中VFPsata11,VFP9090901,VFP9090901是变量的具体值,在VFP中比如用vname,vpass,vsupr作为变量名
1