I've been messing around with protocol handlers in Java, going so far as to write my own using a custom URLStreamHandler and URLConnection. I was implementing the loose methods when I came across URLStreamHandler::openConnection(URL, Proxy). Since I'd already written my logic using Sockets without Proxy support, I decided to write a simple static drop-in proxy layer.

import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class SocketProxy{
    public static Socket proxy(InetSocketAddress destination, Proxy proxy) throws IOException{
        if(proxy == null) proxy = Proxy.NO_PROXY;
        InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address();

            case DIRECT:    // No connection
                Socket directSocket = new Socket();
                return directSocket;
            case SOCKS:     // Simple SOCKS tunnel
                Socket socksProxySocket = new Socket(proxy);
                return socksProxySocket;
            case HTTP:      // HTTP Direct
                StringBuilder headers = new StringBuilder("CONNECT ")

                PasswordAuthentication auth = Authenticator.requestPasswordAuthentication(proxyAddress.getHostName(),
                        proxyAddress.getAddress(), proxyAddress.getPort(), "http",
                        proxyAddress.getHostString(), "http");
                if(auth != null){
                    headers.append(" HTTP/1.0\nProxy-Authorization:Basic ");
                    byte[] userBytes = (auth.getUserName() + ":").getBytes("UTF-8");
                    ByteBuffer passBytes = StandardCharsets.UTF_8.encode(CharBuffer.wrap(auth.getPassword()));
                    ByteBuffer authBytes = ByteBuffer.allocate(userBytes.length + passBytes.capacity());

                Socket httpProxySocket = new Socket();

                InputStream proxyInputStream = httpProxySocket.getInputStream();
                String response = ConnectionUtils.streamToString(proxyInputStream);
                if(response.length() == 0)
                    throw new SocketException("HTTP CONNECT not supported");
                    return httpProxySocket;
                throw new SocketException("HTTP CONNECT failed; check authorization for realm " +
                throw new SocketException("Cannot create socket for connection type: " + proxy.type());

ConnectionUtils (because someone's going to ask):

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class ConnectionUtils{
    public static String streamToString(InputStream stream) throws IOException{
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while((length = stream.read(buffer)) != -1){
            result.write(buffer, 0, length);
        return result.toString("UTF-8");

Sample use case:

protected URLConnection openConnection(URL u, Proxy p) throws IOException{
    return new URLConnection(u){
        private InputStream stream;

        public void connect() throws IOException{
            InetSocketAddress address =
                    new InetSocketAddress(url.getHost(), url.getPort() == -1 ? url.getDefaultPort() : url.getPort());
            Socket socket = SocketProxy.proxy(address, p);

            // Request page
            // ...

            stream = socket.getInputStream();
            connected = true;

        public InputStream getInputStream() throws IOException{
            if(!connected) connect();
            return stream;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.