用了一段时间的eaf browser后,发现自己经常需要访问一些内网服务和google,所以需要频繁切换代理,然后想着给eaf browser实现一个类似pac的黑白名单插件
大概的主体思路就是想在 QNetworkProxyFactory
的 queryProxy
判断黑白名单然后来返回不同的ProxyList
但是,调试的时候发现在queryProxy
中query.url().toString()
取到的 url
总是空的。无法拿来匹配黑白名单的规则
def queryProxy(self, query=None, *args, **kwargs):
protocol = str(query.protocolTag())
url = str(query.url().toString())
if self.shouldUseDefault(protocol, url):
return self._defaultProxyList()
return self._customProxyList()
def shouldUseDefault(self, protocol, url):
if not self.proxy:
return True
if any(re.match(p, url) if isinstance(p, str) else False for p in self.blacklist):
return False
if any(re.match(p, url) if isinstance(p, str) else False for p in self.whitelist):
return True
return bool(self.blacklist)
def _defaultProxyList(self):
return [QNetworkProxy(QNetworkProxy.NoProxy)]
google 了一番得回来得结论感觉是QtWebEngine
的 bug
,无果
A list of QNetworkProxy objects in order of preference.
"""
proxy = config.val.content.proxy
if proxy is configtypes.SYSTEM_PROXY:
# On Linux, use "export http_proxy=socks5://host:port" to manually
# set system proxy.
# ref. https://doc.qt.io/qt-5/qnetworkproxyfactory.html#systemProxyForQuery
proxies = QNetworkProxyFactory.systemProxyForQuery(query)
elif isinstance(proxy, pac.PACFetcher):
if objects.backend == usertypes.Backend.QtWebEngine:
# Looks like query.url() is always invalid on QtWebEngine...
proxy = urlutils.proxy_from_url(QUrl('direct://'))
assert not isinstance(proxy, pac.PACFetcher)
proxies = [proxy]
elif objects.backend == usertypes.Backend.QtWebKit:
proxies = proxy.resolve(query)
else:
raise utils.Unreachable(objects.backend)
else:
proxies = [proxy]
for proxy in proxies:
不知道有没有大佬有更加了解的或者有其他思路的呢?
目前的code:
https://github.com/emacs-eaf/emacs-application-framework/compare/master...EdmondFrank:feat-proxy-plugin?expand=1
要从操作系统看,看看有啥流量重定向的方法,估计更好弄。
我以前折腾过,qwebengine没法自定义规则,没折腾起。
试一下用 BrowserView 的 get_url() 函数?
我怎么感觉逻辑不对啊,BlackWhiteQNetworkProxyFactory感觉是一个全局规则,get_emacs_buffer_url是获取当前显示 Buffer 的 url 作为黑白名单对比。
这个 BlackWhiteQNetworkProxyFactory 不应该跟每个浏览器页面的 URL 对比吗?
按照这个PR, 我在网页里面切换一下,代理逻辑就会乱啊。
是的,最好的方式应该是这个帖子上面一开始提到的 QtNetwork.QNetworkProxyFactory.queryProxy
的[query=QNetworkProxyQuery()]
来获取 url,但是感觉 QtWebEngine
有bug,获取到的 url 总是空的;然后,我又尝试了通过调用 eaf-get-path-or-url
来获取每个浏览器页面对应的 url
的,但是性能太差了,python 和 elisp 的 epc 频繁往复调用容易导致超时。然后,最后写下了这个方案,获取当前 buffer 的 url,这个方案存在的问题,就是大大说的,在切换buffer的时候,url 会不一致,但是在目标 buffer 等待页面加载的时候是 work 的。
应该是你用的方法有问题,我看网上说的 QNetworkProxyFactory 应该和 QNetworkAccessManager 配合着用,关键的函数:
QNetworkAccessManager.setProxyFactory
WebPage.setNetworkAccessManager
query.protocolTag()
你看一下这个下面这几个链接,参考一下别人的实现:
https://github.com/yeyanchao/calibre/blob/e4d06dd27cd4d9139f5acaabda6e11804ab4734b/src/calibre/web/jsbrowser/browser.py
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright © 2015- The Spyder Development Team
# Copyright © 2014-2015 Gonzalo Peña-Castellanos (@goanpeca)
#
# Licensed under the terms of the MIT License
# -----------------------------------------------------------------------------
"""Worker threads for downloading files."""
# Standard library imports
from collections import deque
import json
import os
import re
import sys
# Third party imports
from qtpy.QtCore import QByteArray, QObject, QThread, QTimer, QUrl, Signal
from qtpy.QtNetwork import (QNetworkAccessManager, QNetworkProxy,
QNetworkProxyFactory, QNetworkRequest)
This file has been truncated. show original
还有个下载器的代码
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright © 2015- The Spyder Development Team
# Copyright © 2014-2015 Gonzalo Peña-Castellanos (@goanpeca)
#
# Licensed under the terms of the MIT License
# -----------------------------------------------------------------------------
"""Worker threads for downloading files."""
# Standard library imports
from collections import deque
import json
import os
import re
import sys
# Third party imports
from qtpy.QtCore import QByteArray, QObject, QThread, QTimer, QUrl, Signal
from qtpy.QtNetwork import (QNetworkAccessManager, QNetworkProxy,
QNetworkProxyFactory, QNetworkRequest)
This file has been truncated. show original
QNetworkProxyFactory 和 QNetworkAccessManager 配合用
https://wiki.qt.io/QtWebEngine/Porting_from_QtWebKit
看官方文档的描述,Qt WebEngine 似乎并不能配合着 QNetWorkAccessManager 来使用
用webpage,webpage可以用,你看我上面发的两个链接。
webpage是webengineview的属性
QWebEnginePage 应该才是 WebEngineView的属性
EdmondFrank:
QWebEnginePage
是呀,我的意思是,你按照下面的逻辑来做:
WebEngineView 调用 QWebEnginePage
QWebEnginePage 调用 setNetworkAccessManager
QNetworkAccessManager 调用 setProxyFactory
QProxyFactory 调用 queryProxy 设置代理规则
我估计你按照上面的调用顺序来设置, 你最早的 query.url() 的问题就可以解决
嗯,这个你想表达的流程我了解,但是
QWebEnginePage 并不支持 setNetworkAccessManager
https://doc.qt.io/qt-5/qwebenginepage.html
似乎基于chromium 的 QWebEngine并没有太多Proxy的支持,而NetWorkAccessManager 这些都是基于Webkit的QtWebKit
嗯,那我建议直接操作系统底层库入手,针对EAF进程进行URL规则过滤,不用QT的方法
嗯嗯,还是感谢懒猫大大的耐心回复,和大大的讨论交流中不断查阅文档,我也逐渐知道,是chromium 本身限制了,而不是QtWebEngine的实现bug,哈哈哈。
目前来说,可能直接从系统入手,或者代理层入手设置url规则才是最好的方式。不过,上面的类似 get_url
的方式对我来说也能work (本来还想给eaf贡献贡献的,不过这种蹩脚的实现还是自己玩玩好了),我看看还没有什么优化思路。
懒猫大大,我又查了下Qt的文档,在QtWebEngine下 QWebEngineUrlRequestInterceptor有类似 QProxyFactory 的 queryProxy的捕获请求的功能,基于QWebEngineUrlRequestInterceptor 改了下,我又提交了一版代码。
1 个赞
好的,我周末要带小朋友出去玩一下,估计要晚上回家才能 review code 了,耐心等一下哈。