0

I was trying override the java.net.URL default URLStreamHandler for http and https protocols. I have this working for http request but for some reason that I don't understand yet I can't make it work for HTTPS requests.

This is my custom URLStreamHandler class:

URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
    @Override
    public URLStreamHandler createURLStreamHandler(String protocol) {

        if("http".equals(protocol)) {
            URLStreamHandler streamHandler;
            try {
                streamHandler = (URLStreamHandler) Class.forName("sun.net.www.protocol.http.Handler").newInstance();
                return wrap(streamHandler, currentPRoxy);
            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        } else if("https".equals(protocol)) {
            URLStreamHandler streamHandler;
            try {
                streamHandler = (URLStreamHandler) Class.forName("sun.net.www.protocol.https.Handler").newInstance();
                return wrap(streamHandler, currentPRoxy);
            } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        return null;
    }
});

The wrap method only covers the original URLStreamHandler and add it a custom Header and a Proxy is is setted before. I don't find what I am missing on the HTTPS config to make this work. Some ideas to try fix it?

private static URLStreamHandler wrap(final URLStreamHandler streamHandler, final Proxy p) {
        return new URLStreamHandler() {

            @Override
            protected URLConnection openConnection(URL u) throws IOException {
                URLConnection conn;
                try {

                    if(p != null) {
                        java.lang.reflect.Method openConnectionMethod = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class, Proxy.class);
                        openConnectionMethod.setAccessible(true);
                        conn = (URLConnection) openConnectionMethod.invoke(streamHandler, u, p);
                    } else {
                        java.lang.reflect.Method openConnectionMethod = URLStreamHandler.class.getDeclaredMethod("openConnection", URL.class);
                        openConnectionMethod.setAccessible(true);
                        conn = (URLConnection) openConnectionMethod.invoke(streamHandler, u);
                    }

                 //CUSTOM HEADERS HERE

                    return conn;
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                } catch (IllegalArgumentException e) {
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {
                    if (e.getTargetException() instanceof IOException) {
                        throw (IOException) e.getTargetException();
                    } else {
                        throw new RuntimeException(e);
                    }
                }
            }
    };
}

This is the stack trace:

javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    at sun.security.ssl.InputRecord.handleUnknownRecord(Unknown Source) ~[na:1.8.0_201]
    at sun.security.ssl.InputRecord.read(Unknown Source) ~[na:1.8.0_201]
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) ~[na:1.8.0_201]
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) ~[na:1.8.0_201]
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) ~[na:1.8.0_201]
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source) ~[na:1.8.0_201]
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source) ~[na:1.8.0_201]
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source) ~[na:1.8.0_201]
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source) ~[na:1.8.0_201]
    at com.sun.webkit.network.URLLoader.sendRequest(URLLoader.java:371) [jfxrt.jar:na]
    at com.sun.webkit.network.URLLoader.doRun(URLLoader.java:167) [jfxrt.jar:na]
    at com.sun.webkit.network.URLLoader.lambda$run$98(URLLoader.java:132) [jfxrt.jar:na]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_201]
    at com.sun.webkit.network.URLLoader.run(URLLoader.java:131) [jfxrt.jar:na]
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[na:1.8.0_201]
    at java.util.concurrent.FutureTask.run(Unknown Source) ~[na:1.8.0_201]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:1.8.0_201]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:1.8.0_201]
    at java.lang.Thread.run(Unknown Source) ~[na:1.8.0_201]
Genaut
  • 1,810
  • 2
  • 29
  • 60
  • Your SSL handshake seems failed. Can you connect here with browser? Or try OpenSSL https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html – rockfarkas Mar 03 '19 at 18:40
  • Yep. and If I use the original URLStreamHandler seems working too. – Genaut Mar 03 '19 at 18:41
  • Another hint, why you should test with OpenSSL, because that SSL/TLS version/cypher/etc may be deprecated in your newer java version. – rockfarkas Mar 03 '19 at 19:07
  • @rockfarkas This is all just wild guesswork. The OP's problem is that he is using an HTTPS URL to an HTTP server. The problem isn't even in this code. There is no TLS cipher here at all, and there is no way to use OpenSSL with Java. At least no easy way. – user207421 Mar 03 '19 at 21:30

0 Answers0