How do I write a tunneling HTTP proxy in Java?
Created Sep 28, 2001
Martin Erren [Note: the following is not a full-featured HTTP proxy. Other true HTTP proxies, like Squid, accept the CONNECT request, and can interpret the HTTP headers intelligently. This is a simple tunneling proxy, so it may not work correctly if you set it as your browser's proxy setting. Also, a more full-featured proxy has other features, like caching media. -Alex]
Recently I wrote a little Proxy in java and it works fine tunneling the requests with any ports to tomcat, but I didn't use apache (That's not the reason anyway) and NT instead of WIN98. I think it's either the configuration of the Proxy or the network configuration in your System
try this:
import java.net.*;
import java.io.*;
import java.util.*;
class ProxyConnection extends Thread {
Socket fromClient;
String host;
int port;
long timeout;
ProxyConnection(Socket s, String host, int port, long timeout) {
fromClient=s;
this.host = host;
this.port = port;
this.timeout=timeout;
}
public void run() {
InputStream clientIn = null;
OutputStream clientOut = null;
InputStream serverIn = null;
OutputStream serverOut = null;
Socket toServer = null;
int r0=-1,r1=-1,ch=-1,i=-1;
long time0 = new Date().getTime();
long time1 = new Date().getTime();
try {
toServer = new Socket(host,port);
Proxy.display("open connection to:"+toServer+"(timeout="+timeout+" ms)");
clientIn = fromClient.getInputStream();
clientOut = new BufferedOutputStream(fromClient.getOutputStream());
serverIn = toServer.getInputStream();
serverOut = new BufferedOutputStream(toServer.getOutputStream());
while(r0!=0 || r1!=0 || (time1-time0)<=timeout) {
while((r0=clientIn.available())>0) {
Proxy.println(""); Proxy.println("<<<"+r0+" bytes from client");
Proxy.display(""); Proxy.display("<<<"+r0+" bytes from client");
for(i=0; i<r0; i++) {
ch = clientIn.read();
if(ch!=-1) {
serverOut.write(ch);
Proxy.print(ch);
} else {
Proxy.display("client stream closed");
}
}
time0=new Date().getTime();
serverOut.flush();
}
while((r1=serverIn.available())>0) {
Proxy.println(""); Proxy.println(">>>"+r1+" bytes from server");
Proxy.display(""); Proxy.display(">>>"+r1+" bytes from server");
for(i=0; i<r1; i++) {
ch = serverIn.read();
if(ch!=-1) {
clientOut.write(ch);
Proxy.print(ch);
} else {
Proxy.display("server stream closed");
}
}
time0=new Date().getTime();
clientOut.flush();
}
if(r0==0 && r1==0) {
time1 = new Date().getTime();
Thread.sleep(100);
//Proxy.display("waiting:"+(time1-time0)+" ms");
}
}
} catch(Throwable t) {
Proxy.display("i="+i+" ch="+ch);
t.printStackTrace(System.err);
} finally {
try {
clientIn.close();
clientOut.close();
serverIn.close();
serverOut.close();
fromClient.close();
toServer.close();
Proxy.quit(time1-time0);
} catch(Exception e) {
e.printStackTrace(System.err);
}
}
}
}
public class Proxy {
public static final String usageArgs =" <localport> <host> <port> <timeout_ms>";
static int clientCount;
public static synchronized void print(int i) {
System.out.print((char) i);
}
public static synchronized void println(String s) {
System.out.println(s);
}
public static synchronized void display(String s) {
System.err.println(s);
}
public static synchronized void quit(long t) {
display("...quit after waiting "+t+" ms");
clientCount--;
}
public void run(int localport, String host, int port,long timeout) {
try {
ServerSocket sSocket = new ServerSocket(localport);
while(true) {
Socket cSocket=null;
try {
display("listening...");
cSocket = sSocket.accept();
if(cSocket!=null) {
clientCount++;
display("accepted as #"+clientCount+":"+cSocket);
ProxyConnection c = new ProxyConnection(cSocket,host,port,timeout);
c.run();
}
} catch(Exception e) {
e.printStackTrace(System.err);
}
try {
cSocket.close();
} catch(Exception e) {
//fall thru
}
}
} catch(Throwable t) {
t.printStackTrace(System.err);
}
}
public static void main(String[] argv) {
Proxy self = new Proxy();
if(argv.length>=3) {
int localport = Integer.parseInt(argv[0]);
String url = argv[1];
int port = Integer.parseInt(argv[2]);
int timeout = 30000;
try {
timeout=Integer.parseInt(argv[3]);
} catch(Exception e) {}
self.run(localport,url,port,timeout);
} else {
System.err.println("usage: java " + self.getClass().getName() + usageArgs);
}
}
}//class