Browse Source

support bypassing the proxy for specific hosts

This adds the command line option --bypass-proxy-for which will
bypass the proxy when specific hosts are referenced. It is most
useful for bypassing localhost/127.0.0.1 references
(e.g. --bypass-proxy-for localhost)

This fixes #1565 and #2130
Emil Lerch 10 years ago
parent
commit
7ffec76429

+ 1 - 0
AUTHORS

@@ -32,6 +32,7 @@ Artem Butusov       <art.sormy@gmail.com>
 Michael Nitze       <michael.nitze@online.de>
 Michael Nitze       <michael.nitze@online.de>
 theirix             <theirix@gmail.com>
 theirix             <theirix@gmail.com>
 Kay Lukas           <kay.lukas@gmail.com>
 Kay Lukas           <kay.lukas@gmail.com>
+Emil Lerch          <emil@lerch.org>
 rainabba
 rainabba
 Mehdi Abbad
 Mehdi Abbad
 Lyes Amazouz
 Lyes Amazouz

+ 1 - 0
CHANGELOG.md

@@ -9,6 +9,7 @@ v0.12.3 (unreleased)
 * **#2190**: do not depend on ICU even if it is already installed
 * **#2190**: do not depend on ICU even if it is already installed
 * **#2280**: do not allow data URIs for --header-html or --footer-html
 * **#2280**: do not allow data URIs for --header-html or --footer-html
 * **#2322**: fix broken debug builds with MSVC
 * **#2322**: fix broken debug builds with MSVC
+* **#2355**: add support for proxy bypass for specific hosts with --bypass-proxy-for
 
 
 v0.12.2.1 (2015-01-19)
 v0.12.2.1 (2015-01-19)
 ----------------------
 ----------------------

+ 3 - 0
include/wkhtmltox/loadsettings.hh

@@ -117,6 +117,9 @@ struct DLL_PUBLIC LoadPage {
 
 
 	QString cacheDir;
 	QString cacheDir;
 	static QList<QString> mediaFilesExtensions;
 	static QList<QString> mediaFilesExtensions;
+
+	// Hosts to bypass
+	QList< QString > bypassProxyForHosts;
 };
 };
 
 
 DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);
 DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);

+ 3 - 0
src/lib/loadsettings.hh

@@ -120,6 +120,9 @@ struct DLL_PUBLIC LoadPage {
 
 
 	QString cacheDir;
 	QString cacheDir;
 	static QList<QString> mediaFilesExtensions;
 	static QList<QString> mediaFilesExtensions;
+
+	// Hosts to bypass
+	QList< QString > bypassProxyForHosts;
 };
 };
 
 
 DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);
 DLL_PUBLIC LoadPage::LoadErrorHandling strToLoadErrorHandling(const char * s, bool * ok=0);

+ 18 - 1
src/lib/multipageloader.cc

@@ -107,6 +107,19 @@ QNetworkReply * MyNetworkAccessManager::createRequest(Operation op, const QNetwo
 	return QNetworkAccessManager::createRequest(op, r3, outgoingData);
 	return QNetworkAccessManager::createRequest(op, r3, outgoingData);
 }
 }
 
 
+MyNetworkProxyFactory::MyNetworkProxyFactory (QNetworkProxy proxy, QList<QString> bph):
+	bypassHosts(bph),
+	originalProxy(QList<QNetworkProxy>() << proxy),
+	noProxy(QList<QNetworkProxy>() << QNetworkProxy(QNetworkProxy::DefaultProxy)){}
+
+QList<QNetworkProxy> MyNetworkProxyFactory::queryProxy (const QNetworkProxyQuery & query) {
+	QString host = query.url().host();
+	foreach (const QString & bypassHost, bypassHosts) {
+		if (host.compare(bypassHost, Qt::CaseInsensitive) == 0)
+			return noProxy;
+	}
+	return originalProxy;
+}
 
 
 MyQWebPage::MyQWebPage(ResourceObject & res): resource(res) {}
 MyQWebPage::MyQWebPage(ResourceObject & res): resource(res) {}
 
 
@@ -192,7 +205,11 @@ ResourceObject::ResourceObject(MultiPageLoaderPrivate & mpl, const QUrl & u, con
 			proxy.setUser(settings.proxy.user);
 			proxy.setUser(settings.proxy.user);
 		if (!settings.proxy.password.isEmpty())
 		if (!settings.proxy.password.isEmpty())
 			proxy.setPassword(settings.proxy.password);
 			proxy.setPassword(settings.proxy.password);
-		networkAccessManager.setProxy(proxy);
+		if (!settings.bypassProxyForHosts.isEmpty())
+			networkAccessManager.setProxyFactory(
+				new MyNetworkProxyFactory(proxy, settings.bypassProxyForHosts));
+		else
+			networkAccessManager.setProxy(proxy);
 	}
 	}
 
 
 	webPage.setNetworkAccessManager(&networkAccessManager);
 	webPage.setNetworkAccessManager(&networkAccessManager);

+ 10 - 0
src/lib/multipageloader_p.hh

@@ -35,6 +35,16 @@
 #include "dllbegin.inc"
 #include "dllbegin.inc"
 namespace wkhtmltopdf {
 namespace wkhtmltopdf {
 
 
+class DLL_LOCAL MyNetworkProxyFactory: public QObject, public QNetworkProxyFactory {
+	Q_OBJECT
+private:
+	QList<QString> bypassHosts;
+	QList<QNetworkProxy> originalProxy, noProxy;
+public:
+	MyNetworkProxyFactory(QNetworkProxy defaultProxy, QList<QString> bypassHosts);
+	QList<QNetworkProxy> queryProxy (const QNetworkProxyQuery & query);
+};
+
 class DLL_LOCAL MyNetworkAccessManager: public QNetworkAccessManager {
 class DLL_LOCAL MyNetworkAccessManager: public QNetworkAccessManager {
 	Q_OBJECT
 	Q_OBJECT
 private:
 private:

+ 1 - 0
src/lib/reflect.cc

@@ -76,6 +76,7 @@ ReflectImpl<LoadPage>::ReflectImpl(LoadPage & c) {
 	WKHTMLTOPDF_REFLECT(radiobuttonSvg);
 	WKHTMLTOPDF_REFLECT(radiobuttonSvg);
 	WKHTMLTOPDF_REFLECT(radiobuttonCheckedSvg);
 	WKHTMLTOPDF_REFLECT(radiobuttonCheckedSvg);
 	WKHTMLTOPDF_REFLECT(cacheDir);
 	WKHTMLTOPDF_REFLECT(cacheDir);
+	WKHTMLTOPDF_REFLECT(bypassProxyForHosts);
 }
 }
 
 
 ReflectImpl<Web>::ReflectImpl(Web & c) {
 ReflectImpl<Web>::ReflectImpl(Web & c) {

+ 1 - 0
src/shared/commonarguments.cc

@@ -203,6 +203,7 @@ void CommandLineParserBase::addPageLoadArgs(LoadPage & s) {
 	extended(true);
 	extended(true);
 	qthack(false);
 	qthack(false);
 	addarg("proxy",'p',"Use a proxy", new ProxySetter(s.proxy, "proxy"));
 	addarg("proxy",'p',"Use a proxy", new ProxySetter(s.proxy, "proxy"));
+	addarg("bypass-proxy-for", 0, "Bypass proxy for host (repeatable)", new StringListSetter(s.bypassProxyForHosts, "value"));
 	addarg("username",0,"HTTP Authentication username", new QStrSetter(s.username, "username"));
 	addarg("username",0,"HTTP Authentication username", new QStrSetter(s.username, "username"));
 	addarg("password",0,"HTTP Authentication password", new QStrSetter(s.password, "password"));
 	addarg("password",0,"HTTP Authentication password", new QStrSetter(s.password, "password"));
 	addarg("load-error-handling", 0, "Specify how to handle pages that fail to load: abort, ignore or skip", new LoadErrorHandlingSetting(s.loadErrorHandling, "handler"));
 	addarg("load-error-handling", 0, "Specify how to handle pages that fail to load: abort, ignore or skip", new LoadErrorHandlingSetting(s.loadErrorHandling, "handler"));