1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mortbay.servlet;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.OutputStream;
21 import java.net.HttpURLConnection;
22 import java.net.InetSocketAddress;
23 import java.net.Socket;
24 import java.net.URL;
25 import java.net.URLConnection;
26 import java.util.Enumeration;
27 import java.util.HashSet;
28
29 import javax.servlet.Servlet;
30 import javax.servlet.ServletConfig;
31 import javax.servlet.ServletContext;
32 import javax.servlet.ServletException;
33 import javax.servlet.ServletRequest;
34 import javax.servlet.ServletResponse;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
37
38 import org.mortbay.util.IO;
39
40
41
42
43
44
45
46
47 public class ProxyServlet implements Servlet
48 {
49
50 protected HashSet _DontProxyHeaders = new HashSet();
51 {
52 _DontProxyHeaders.add("proxy-connection");
53 _DontProxyHeaders.add("connection");
54 _DontProxyHeaders.add("keep-alive");
55 _DontProxyHeaders.add("transfer-encoding");
56 _DontProxyHeaders.add("te");
57 _DontProxyHeaders.add("trailer");
58 _DontProxyHeaders.add("proxy-authorization");
59 _DontProxyHeaders.add("proxy-authenticate");
60 _DontProxyHeaders.add("upgrade");
61 }
62
63 private ServletConfig config;
64 private ServletContext context;
65
66
67
68
69 public void init(ServletConfig config) throws ServletException
70 {
71 this.config=config;
72 this.context=config.getServletContext();
73 }
74
75
76
77
78 public ServletConfig getServletConfig()
79 {
80 return config;
81 }
82
83
84
85
86 public void service(ServletRequest req, ServletResponse res) throws ServletException,
87 IOException
88 {
89 HttpServletRequest request = (HttpServletRequest)req;
90 HttpServletResponse response = (HttpServletResponse)res;
91 if ("CONNECT".equalsIgnoreCase(request.getMethod()))
92 {
93 handleConnect(request,response);
94 }
95 else
96 {
97 String uri=request.getRequestURI();
98 if (request.getQueryString()!=null)
99 uri+="?"+request.getQueryString();
100 URL url = new URL(request.getScheme(),
101 request.getServerName(),
102 request.getServerPort(),
103 uri);
104
105 context.log("URL="+url);
106
107 URLConnection connection = url.openConnection();
108 connection.setAllowUserInteraction(false);
109
110
111 HttpURLConnection http = null;
112 if (connection instanceof HttpURLConnection)
113 {
114 http = (HttpURLConnection)connection;
115 http.setRequestMethod(request.getMethod());
116 http.setInstanceFollowRedirects(false);
117 }
118
119
120 String connectionHdr = request.getHeader("Connection");
121 if (connectionHdr!=null)
122 {
123 connectionHdr=connectionHdr.toLowerCase();
124 if (connectionHdr.equals("keep-alive")||
125 connectionHdr.equals("close"))
126 connectionHdr=null;
127 }
128
129
130 boolean xForwardedFor=false;
131 boolean hasContent=false;
132 Enumeration enm = request.getHeaderNames();
133 while (enm.hasMoreElements())
134 {
135
136 String hdr=(String)enm.nextElement();
137 String lhdr=hdr.toLowerCase();
138
139 if (_DontProxyHeaders.contains(lhdr))
140 continue;
141 if (connectionHdr!=null && connectionHdr.indexOf(lhdr)>=0)
142 continue;
143
144 if ("content-type".equals(lhdr))
145 hasContent=true;
146
147 Enumeration vals = request.getHeaders(hdr);
148 while (vals.hasMoreElements())
149 {
150 String val = (String)vals.nextElement();
151 if (val!=null)
152 {
153 connection.addRequestProperty(hdr,val);
154 context.log("req "+hdr+": "+val);
155 xForwardedFor|="X-Forwarded-For".equalsIgnoreCase(hdr);
156 }
157 }
158 }
159
160
161 connection.setRequestProperty("Via","1.1 (jetty)");
162 if (!xForwardedFor)
163 connection.addRequestProperty("X-Forwarded-For",
164 request.getRemoteAddr());
165
166
167 String cache_control = request.getHeader("Cache-Control");
168 if (cache_control!=null &&
169 (cache_control.indexOf("no-cache")>=0 ||
170 cache_control.indexOf("no-store")>=0))
171 connection.setUseCaches(false);
172
173
174
175 try
176 {
177 connection.setDoInput(true);
178
179
180 InputStream in=request.getInputStream();
181 if (hasContent)
182 {
183 connection.setDoOutput(true);
184 IO.copy(in,connection.getOutputStream());
185 }
186
187
188 connection.connect();
189 }
190 catch (Exception e)
191 {
192 context.log("proxy",e);
193 }
194
195 InputStream proxy_in = null;
196
197
198 int code=500;
199 if (http!=null)
200 {
201 proxy_in = http.getErrorStream();
202
203 code=http.getResponseCode();
204 response.setStatus(code, http.getResponseMessage());
205 context.log("response = "+http.getResponseCode());
206 }
207
208 if (proxy_in==null)
209 {
210 try {proxy_in=connection.getInputStream();}
211 catch (Exception e)
212 {
213 context.log("stream",e);
214 proxy_in = http.getErrorStream();
215 }
216 }
217
218
219 response.setHeader("Date",null);
220 response.setHeader("Server",null);
221
222
223 int h=0;
224 String hdr=connection.getHeaderFieldKey(h);
225 String val=connection.getHeaderField(h);
226 while(hdr!=null || val!=null)
227 {
228 String lhdr = hdr!=null?hdr.toLowerCase():null;
229 if (hdr!=null && val!=null && !_DontProxyHeaders.contains(lhdr))
230 response.addHeader(hdr,val);
231
232 context.log("res "+hdr+": "+val);
233
234 h++;
235 hdr=connection.getHeaderFieldKey(h);
236 val=connection.getHeaderField(h);
237 }
238 response.addHeader("Via","1.1 (jetty)");
239
240
241 if (proxy_in!=null)
242 IO.copy(proxy_in,response.getOutputStream());
243
244 }
245 }
246
247
248
249 public void handleConnect(HttpServletRequest request,
250 HttpServletResponse response)
251 throws IOException
252 {
253 String uri = request.getRequestURI();
254
255 context.log("CONNECT: "+uri);
256
257 String port = "";
258 String host = "";
259
260 int c = uri.indexOf(':');
261 if (c>=0)
262 {
263 port = uri.substring(c+1);
264 host = uri.substring(0,c);
265 if (host.indexOf('/')>0)
266 host = host.substring(host.indexOf('/')+1);
267 }
268
269
270
271
272 InetSocketAddress inetAddress = new InetSocketAddress (host, Integer.parseInt(port));
273
274
275
276
277
278
279 {
280 InputStream in=request.getInputStream();
281 OutputStream out=response.getOutputStream();
282
283 Socket socket = new Socket(inetAddress.getAddress(),inetAddress.getPort());
284 context.log("Socket: "+socket);
285
286 response.setStatus(200);
287 response.setHeader("Connection","close");
288 response.flushBuffer();
289
290
291
292 context.log("out<-in");
293 IO.copyThread(socket.getInputStream(),out);
294 context.log("in->out");
295 IO.copy(in,socket.getOutputStream());
296 }
297 }
298
299
300
301
302
303
304
305 public String getServletInfo()
306 {
307 return "Proxy Servlet";
308 }
309
310
311
312
313 public void destroy()
314 {
315
316 }
317 }