Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save naeemrashid/11e09adae1f4913cb26f72fa4d34ee1a to your computer and use it in GitHub Desktop.
Save naeemrashid/11e09adae1f4913cb26f72fa4d34ee1a to your computer and use it in GitHub Desktop.
Hack for allowing dedicated proxy settings to be used for URL with http and https protocol handling in JavaFXs Webkit based WebView. Tested with JDK8

Run with:

-Dhttp.proxy=none.local
-Dhttp.proxyPort=1234
-Dhack.webkit.http.proxy=localhost
-Dhack.webkit.http.proxyPort=8080

I used -Dhttp.proxy=none.local and -Dhttp.proxyPort=1234 to "simulate" a non working default proxy configuration for all "other" URL load requests.

package de.tutorials.training.fx.proxy;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import java.net.InetSocketAddress;
import java.net.Proxy;
/**
* @author Thomas Darimont
*/
public class ProxyProblemExample extends Application {
@Override
public void start(Stage stage) throws Exception {
StackPane root = new StackPane();
WebView view = new WebView();
WebEngine engine = view.getEngine();
engine.load("https://www.google.com");
root.getChildren().add(view);
Scene scene = new Scene(root, 960, 640);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) throws Exception {
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(System.getProperty("hack.webkit.http.proxy"), Integer.getInteger("hack.webkit.http.proxyPort")));
URLStreamFactoryCustomizer.useDedicatedProxyForWebkit(proxy, "http, https");
Application.launch(ProxyProblemExample.class);
}
}
package de.tutorials.training.fx.proxy;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.util.Hashtable;
import java.util.function.Consumer;
import static java.util.Arrays.asList;
/**
* @author Thomas Darimont
*/
public class URLStreamFactoryCustomizer {
public static void useDedicatedProxyForWebkit(Proxy proxy, String protocols) {
forceInitializationOfOriginalUrlStreamHandlers();
tryReplaceOriginalUrlStreamHandlersWithScopeProxyAwareVariants(proxy, protocols);
}
private static void tryReplaceOriginalUrlStreamHandlersWithScopeProxyAwareVariants(Proxy proxy, String protocols) {
try {
Hashtable handlers = tryExtractInternalHandlerTableFromUrl();
//System.out.println(handlers);
Consumer<String> wrapStreamHandlerWithScopedProxyHandler = protocol ->
{
URLStreamHandler originalHandler = (URLStreamHandler) handlers.get(protocol);
handlers.put(protocol, new DelegatingScopedProxyAwareUrlStreamHandler(originalHandler, proxy));
};
asList(protocols.split(",")).stream().map(String::trim).filter(s -> !s.isEmpty()).forEach(wrapStreamHandlerWithScopedProxyHandler);
//System.out.println(handlers);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private static Hashtable tryExtractInternalHandlerTableFromUrl() {
try {
Field handlersField = URL.class.getDeclaredField("handlers");
handlersField.setAccessible(true);
return (Hashtable) handlersField.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void forceInitializationOfOriginalUrlStreamHandlers() {
try {
new URL("http://.");
new URL("https://.");
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
static class DelegatingScopedProxyAwareUrlStreamHandler extends URLStreamHandler {
private static final Method openConnectionMethod;
private static final Method openConnectionWithProxyMethod;
static {
try {
openConnectionMethod = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class);
openConnectionWithProxyMethod = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, Proxy.class);
openConnectionMethod.setAccessible(true);
openConnectionWithProxyMethod.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private final URLStreamHandler delegatee;
private final Proxy proxy;
public DelegatingScopedProxyAwareUrlStreamHandler(URLStreamHandler delegatee, Proxy proxy) {
this.delegatee = delegatee;
this.proxy = proxy;
}
@Override
protected URLConnection openConnection(URL url) throws IOException {
try {
if (isWebKitURLLoaderThread(Thread.currentThread())) {
//WebKit requested loading the given url, use provided proxy.
return (URLConnection) openConnectionWithProxyMethod.invoke(delegatee, url, proxy);
}
//Invoke the standard url handler.
return (URLConnection) openConnectionMethod.invoke(delegatee, url);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private boolean isWebKitURLLoaderThread(Thread thread) {
StackTraceElement[] st = thread.getStackTrace();
//TODO Add more robust stack-trace inspection.
return st.length > 4 && st[4].getClassName().startsWith("com.sun.webkit.network");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment