1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.apache.commons.httpclient.server;
32
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.InterruptedIOException;
36 import java.io.OutputStream;
37 import java.net.Socket;
38
39 import org.apache.commons.httpclient.Header;
40 import org.apache.commons.httpclient.HttpStatus;
41 import org.apache.commons.httpclient.HttpVersion;
42
43 /***
44 * This request handler can handle the CONNECT method. It does nothing for any
45 * other HTTP methods.
46 *
47 * @author Ortwin Glueck
48 */
49 public class TransparentProxyRequestHandler implements HttpRequestHandler {
50
51
52
53
54
55
56 public boolean processRequest(
57 final SimpleHttpServerConnection conn,
58 final SimpleRequest request) throws IOException
59 {
60
61 RequestLine line = request.getRequestLine();
62 HttpVersion ver = line.getHttpVersion();
63 String method = line.getMethod();
64 if (!"CONNECT".equalsIgnoreCase(method)) {
65 return false;
66 }
67 Socket targetSocket = null;
68 try {
69 targetSocket = connect(line.getUri());
70 } catch (IOException e) {
71 SimpleResponse response = new SimpleResponse();
72 response.setStatusLine(ver, HttpStatus.SC_NOT_FOUND);
73 response.setHeader(new Header("Server", "test proxy"));
74 response.setBodyString("Cannot connect to " + line.getUri());
75 conn.writeResponse(response);
76 return true;
77 }
78 SimpleResponse response = new SimpleResponse();
79 response.setHeader(new Header("Server", "test proxy"));
80 response.setStatusLine(ver, HttpStatus.SC_OK, "Connection established");
81 conn.writeResponse(response);
82
83 SimpleHttpServerConnection target = new SimpleHttpServerConnection(targetSocket);
84 pump(conn, target);
85 return true;
86 }
87
88 private void pump(final SimpleHttpServerConnection source, final SimpleHttpServerConnection target)
89 throws IOException {
90
91 source.setSocketTimeout(100);
92 target.setSocketTimeout(100);
93
94 InputStream sourceIn = source.getInputStream();
95 OutputStream sourceOut = source.getOutputStream();
96 InputStream targetIn = target.getInputStream();
97 OutputStream targetOut = target.getOutputStream();
98
99 byte[] tmp = new byte[1024];
100 int l;
101 for (;;) {
102 if (!source.isOpen() || !target.isOpen()) {
103 break;
104 }
105 try {
106 l = sourceIn.read(tmp);
107 if (l == -1) {
108 break;
109 }
110 targetOut.write(tmp, 0, l);
111 } catch (InterruptedIOException ignore) {
112 if (Thread.interrupted()) {
113 break;
114 }
115 }
116 try {
117 l = targetIn.read(tmp);
118 if (l == -1) {
119 break;
120 }
121 sourceOut.write(tmp, 0, l);
122 } catch (InterruptedIOException ignore) {
123 if (Thread.interrupted()) {
124 break;
125 }
126 }
127 }
128 }
129
130 private static Socket connect(final String host) throws IOException {
131 String hostname = null;
132 int port;
133 int i = host.indexOf(':');
134 if (i != -1) {
135 hostname = host.substring(0, i);
136 try {
137 port = Integer.parseInt(host.substring(i + 1));
138 } catch (NumberFormatException ex) {
139 throw new IOException("Invalid host address: " + host);
140 }
141 } else {
142 hostname = host;
143 port = 80;
144 }
145 return new Socket(hostname, port);
146 }
147
148 }