1 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.Socket ; 23 import java.net.URL ; 24 import java.net.URLConnection ; 25 import java.util.Enumeration ; 26 import java.util.HashSet ; 27 28 import javax.servlet.Servlet ; 29 import javax.servlet.ServletConfig ; 30 import javax.servlet.ServletContext ; 31 import javax.servlet.ServletException ; 32 import javax.servlet.ServletRequest ; 33 import javax.servlet.ServletResponse ; 34 import javax.servlet.http.HttpServletRequest ; 35 import javax.servlet.http.HttpServletResponse ; 36 37 import org.mortbay.util.IO; 38 import org.mortbay.util.InetAddrPort; 39 40 41 46 public class ProxyServlet implements Servlet 47 { 48 private int _tunnelTimeoutMs=3000; 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 69 public void init(ServletConfig config) throws ServletException 70 { 71 this.config=config; 72 this.context=config.getServletContext(); 73 } 74 75 78 public ServletConfig getServletConfig() 79 { 80 return config; 81 } 82 83 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 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 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 boolean xForwardedFor=false; 131 boolean hasContent=false; 132 Enumeration enm = request.getHeaderNames(); 133 while (enm.hasMoreElements()) 134 { 135 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 connection.setRequestProperty("Via","1.1 (jetty)"); 162 if (!xForwardedFor) 163 connection.addRequestProperty("X-Forwarded-For", 164 request.getRemoteAddr()); 165 166 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 175 try 176 { 177 connection.setDoInput(true); 178 179 InputStream in=request.getInputStream(); 181 if (hasContent) 182 { 183 connection.setDoOutput(true); 184 IO.copy(in,connection.getOutputStream()); 185 } 186 187 connection.connect(); 189 } 190 catch (Exception e) 191 { 192 context.log("proxy",e); 193 } 194 195 InputStream proxy_in = null; 196 197 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 response.setHeader("Date",null); 220 response.setHeader("Server",null); 221 222 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 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 InetAddrPort addrPort=new InetAddrPort(uri); 258 259 { 265 InputStream in=request.getInputStream(); 266 OutputStream out=response.getOutputStream(); 267 268 Socket socket = new Socket (addrPort.getInetAddress(),addrPort.getPort()); 269 context.log("Socket: "+socket); 270 271 response.setStatus(200); 272 response.setHeader("Connection","close"); 273 response.flushBuffer(); 274 275 System.err.println(response); 276 277 context.log("out<-in"); 278 IO.copyThread(socket.getInputStream(),out); 279 context.log("in->out"); 280 IO.copy(in,socket.getOutputStream()); 281 } 282 } 283 284 285 286 287 290 public String getServletInfo() 291 { 292 return "Proxy Servlet"; 293 } 294 295 298 public void destroy() 299 { 300 301 } 302 } 303 | Popular Tags |