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(); } } }