Proxy input/output stream issues in Java
I've been trying for a while a few different methods to get my custom proxy to work, and the only way I've been able to so far is through use of Apache's HttpClient. However, for the sake of knowing, I was wondering why I'm having trouble with my own proxy handle implementation below:
public void processProxyRequest (Socket client, String request) throws Exception {
if ( !request.equals("") ) {
String[] requestHeaders = request.split("\\r\\n");
Pattern p = Pattern.compile("([A-Z]*)\\s*([^:\\/]*):\\/\\/([^\\s]*)\\s*(?:HTTP.*)");
Matcher m = p.matcher(requestHeaders[0]);
if ( m.matches() ) {
String method = m.group(1).toUpperCase();
String proto = m.group(2).toLowerCase();
String[] requestInfo = m.group(3).split("\\/", 2);
String host = requestInfo[0];
host = ( host.split("\\.").length < 3 ) ? "www." + host : host;
String page = "/";
if ( requestInfo.length == 2 && !requestInfo[1].equals("") ) {
page += requestInfo[1];
}
int remotePort = 80;
if ( proto.equals("https") ) {
remotePort = 443;
}
else开发者_运维百科 if ( proto.equals("ftp") ) {
remotePort = 21;
}
this.sendAndReceive(client, request, host, remotePort);
}
}
}
public void sendAndReceive (Socket client, String request, String host, int port) throws Exception {
Socket target = new Socket(host, port);
System.out.println("Connected to server");
ByteArrayInputStream inStream = new ByteArrayInputStream(request.getBytes());
this.inToOut(inStream, target.getOutputStream());
System.out.println("Sent");
this.inToOut(target.getInputStream(), client.getOutputStream());
System.out.println("Received");
target.close();
}
public void inToOut (InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024]; // Adjust if you want
int bytesRead;
System.out.println("reading");
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
}
In a nutshell (and disregarding my request header parsing flaws), the above code compiles and runs, however, the inToOut()
method seems to struggle a bit and lock up during the input.read(), and I'm not too sure why. I do know as a fact that the original socket I'm passing in is valid and opened without errors. Additionally, the System.out
in the inToOut() function does print "reading" but never gets past the read()
portion.
Thank you for any suggestions!
This is no way to write a proxy. In the case of HTTP you only have to process the first line, that tells you the target host. Everything else is just copying bytes back and forth, subject to a couple of minor refinements such as reporting upstream connect errors correctly snd handling shutdowns properly. The FTP case is trickier and should be handled completely separately, but again once you get past the connect phase it's just copying bytes around. The less effortmyou make to understand the protocol the simpler and better it gets.
In your sendAndReceive function, perhaps try using DataInputStream and DataOutputStream
public void sendAndReceive (Socket client, String request, String host, int port) throws Exception {
Socket target = new Socket(host, port);
System.out.println("Connected to server");
this.inToOut(new DataInputStream(client.getInputStream()), new DataOutputStream(target.getOutputStream()));
System.out.println("Sent");
this.inToOut(new DataInputStream(target.getInputStream()), new DataOutputStream(client.getOutputStream()));
System.out.println("Received");
target.close();
}
The problem doesn't seem to be in the inToOut function - I've tried using inToOut() and it works fine (it actually helped me fix a problem I was having with something similar - Thanks)
精彩评论