用了一段时间的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
,无果
opened 06:59AM - 31 Mar 17 UTC
priority: 1 - middle
component: QtWebEngine
qt: 5.13
There's no PAC support in QtWebEngine currently.
To use Chromium's PAC implem… entation, we need to set the `auto_proxy` environment variable (i.e. it'll require a restart) and then disable the application proxy factory.
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:
要从操作系统看,看看有啥流量重定向的方法,估计更好弄。
我以前折腾过,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()
你看一下这个下面这几个链接,参考一下别人的实现:
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <[email protected] >'
__docformat__ = 'restructuredtext en'
import os, pprint, time
from cookielib import Cookie
from PyQt4.Qt import (QObject, QNetworkAccessManager, QNetworkDiskCache,
QNetworkProxy, QNetworkProxyFactory, QEventLoop, QUrl,
QDialog, QVBoxLayout, QSize, QNetworkCookieJar)
from PyQt4.QtWebKit import QWebPage, QWebSettings, QWebView, QWebElement
from calibre import USER_AGENT, prints, get_proxies, get_proxy_info
from calibre.constants import ispy3, config_dir
from calibre.utils.logging import ThreadSafeLog
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
还有个下载器的代码
# -*- 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 了,耐心等一下哈。