Monday, 11 July 2011

HTTP Proxy

Sometimes you just want a simple HTTP proxy without the hastle.

HttpProxy.java

package org.adrianwalker.httpproxy;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public final class HttpProxy {

  public static final int MAX_THREADS = 2;
  public static final int LOCAL_PORT = 9090;
  public static final String REMOTE_HOST = "localhost";
  public static final int REMOTE_PORT = 8080;

  public static void main(final String[] args) throws Exception {

    ServerSocket server = new ServerSocket(LOCAL_PORT);

    Socket remoteSocket = new Socket(REMOTE_HOST, REMOTE_PORT);
    while (true) {
      Socket localSocket = server.accept();

      ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
      executor.submit(new SocketStreamCopy(remoteSocket.getInputStream(), localSocket.getOutputStream()));
      executor.submit(new SocketStreamCopy(localSocket.getInputStream(), remoteSocket.getOutputStream()));
    }
  }

  public static final class SocketStreamCopy implements Callable<Void> {

    public static final int BUFFER_SIZE = 1024;
    private final BufferedInputStream in;
    private final BufferedOutputStream out;

    SocketStreamCopy(final InputStream in, final OutputStream out) {

      this.in = new BufferedInputStream(in);
      this.out = new BufferedOutputStream(out);
    }

    @Override
    public Void call() throws Exception {
      byte[] b = new byte[BUFFER_SIZE];
      int n;
      try {
        while ((n = in.read(b)) > 0) {
          out.write(b, 0, n);
          out.flush();

          System.out.write(b, 0, n);
          System.out.flush();
        }
      } finally {
        in.close();
        out.close();
      }

      return Void.TYPE.newInstance();
    }
  }
}