Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect a Socket server via HTTP proxy

I have a piece of code to connect to a Socket server, and it works fine.

Socket socket = new Socket();
socket.connect(new InetSocketAddress(address, port));

Now I want to connect via a HTTP proxy, what should I do?

I tried this and failed

SocketAddress proxyAddr = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr);
Socket socket = new Socket(proxy);
socket.connect(new InetSocketAddress(address, port));

this post suggests that I should use Jakarta Commons HttpClient, but how to use it to connect a Socket server via the HTTP proxy?

UPDATED: I used SOCKS proxy and it doesn't work, if I use HTTP proxy:

SocketAddress proxyAddr = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
Socket socket = new Socket(proxy);
socket.connect(new InetSocketAddress(address, port));

and it will throw an IllegalArgumentException

java.lang.IllegalArgumentException: Proxy is null or invalid type
    at java.net.Socket.<init>(Socket.java:88)
like image 737
Johnny Avatar asked Aug 29 '11 03:08

Johnny


People also ask

What is https proxyHost?

The http. proxyHost property must be defined to configure an HTTP proxy, and https. proxyHost for a HTTPS proxy. The http.proxyHost and http.proxyPort properties indicate the proxy server and the port that the HTTP protocol handler will use.


1 Answers

I've created small Socket Factory class to handle the HTTP CONNECT via socket. The socket then can be used as per-normal provided the proxy supports CONNECT to the destination.

public final class SocketFactory {

    public static Socket GetSocket(String host, String port) throws IOException {

        /*************************
         * Get the jvm arguments
         *************************/

        int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort"));
        String proxyHost = System.getProperty("http.proxyHost");

        // Socket object connecting to proxy
        Socket sock = new Socket(proxyHost, proxyPort);

        /***********************************
         * HTTP CONNECT protocol RFC 2616
         ***********************************/
        String proxyConnect = "CONNECT " + host + ":" + port;

        // Add Proxy Authorization if proxyUser and proxyPass is set
        try {
            String proxyUserPass = String.format("%s:%s",
                    System.getProperty("http.proxyUser"),
                    System.getProperty("http.proxyPass"));

            proxyConnect.concat(" HTTP/1.0\nProxy-Authorization:Basic "
                    + Base64.encode(proxyUserPass.getBytes()));
        } catch (Exception e) {
        } finally {
            proxyConnect.concat("\n\n");
        }

        sock.getOutputStream().write(proxyConnect.getBytes());
        /***********************************/

        /***************************
         * validate HTTP response.
         ***************************/
        byte[] tmpBuffer = new byte[512];
        InputStream socketInput = sock.getInputStream();

        int len = socketInput.read(tmpBuffer, 0, tmpBuffer.length);

        if (len == 0) {
            throw new SocketException("Invalid response from proxy");
        }

        String proxyResponse = new String(tmpBuffer, 0, len, "UTF-8");

        // Expecting HTTP/1.x 200 OK
        if (proxyResponse.indexOf("200") != -1) {

            // Flush any outstanding message in buffer
            if (socketInput.available() > 0)
                socketInput.skip(socketInput.available());

            // Proxy Connect Successful, return the socket for IO
            return sock;
        } else {
            throw new SocketFactoryException("Fail to create Socket",
                    proxyResponse);
        }
    }

    /**
     * Simplest Base64 Encoder adopted from GeorgeK
     * 
     * @see http://stackoverflow.com/questions/469695/decode-base64-data-in-java/4265472#4265472
     */
    private static class Base64 {
        /***********************
         * Base64 character set
         ***********************/
        private final static char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
                .toCharArray();

        /**
         * Translates the specified byte array into Base64 string.
         * 
         * @param buf
         *            the byte array (not null)
         * @return the translated Base64 string (not null)
         */
        public static String encode(byte[] buf) {
            int size = buf.length;
            char[] ar = new char[((size + 2) / 3) * 4];
            int a = 0;
            int i = 0;
            while (i < size) {
                byte b0 = buf[i++];
                byte b1 = (i < size) ? buf[i++] : 0;
                byte b2 = (i < size) ? buf[i++] : 0;

                int mask = 0x3F;
                ar[a++] = ALPHABET[(b0 >> 2) & mask];
                ar[a++] = ALPHABET[((b0 << 4) | ((b1 & 0xFF) >> 4)) & mask];
                ar[a++] = ALPHABET[((b1 << 2) | ((b2 & 0xFF) >> 6)) & mask];
                ar[a++] = ALPHABET[b2 & mask];
            }
            switch (size % 3) {
            case 1:
                ar[--a] = '=';
            case 2:
                ar[--a] = '=';
            }
            return new String(ar);
        }
    }
}

https://code.google.com/p/java-socket-over-http-proxy-connect/

like image 187
Ernest Neo Avatar answered Sep 21 '22 16:09

Ernest Neo