View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  package com.eviware.soapui.impl.wsdl.monitor.jettyproxy;
13  
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.io.OutputStream;
17  import java.net.InetSocketAddress;
18  import java.net.Socket;
19  import java.util.Enumeration;
20  import java.util.HashSet;
21  
22  import javax.servlet.Servlet;
23  import javax.servlet.ServletConfig;
24  import javax.servlet.ServletContext;
25  import javax.servlet.ServletException;
26  import javax.servlet.ServletRequest;
27  import javax.servlet.ServletResponse;
28  import javax.servlet.http.HttpServletRequest;
29  import javax.servlet.http.HttpServletResponse;
30  
31  import org.mortbay.jetty.HttpSchemes;
32  import org.mortbay.jetty.client.HttpClient;
33  import org.mortbay.util.IO;
34  import org.mortbay.util.ajax.Continuation;
35  import org.mortbay.util.ajax.ContinuationSupport;
36  
37  import com.eviware.soapui.impl.wsdl.WsdlProject;
38  import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange;
39  import com.eviware.soapui.impl.wsdl.monitor.SoapMonitor;
40  
41  public class ProxyServlet implements Servlet
42  {
43  
44  	private ServletConfig config;
45  	private ServletContext context;
46  	private HttpClient client;
47  	private JProxyServletWsdlMonitorMessageExchange capturedData;
48  	private SoapMonitor monitor;
49  	private WsdlProject project;
50  
51  	static HashSet<String> dontProxyHeaders = new HashSet<String>();
52  	{
53  		dontProxyHeaders.add("proxy-connection");
54  		dontProxyHeaders.add("connection");
55  		dontProxyHeaders.add("keep-alive");
56  		dontProxyHeaders.add("transfer-encoding");
57  		dontProxyHeaders.add("te");
58  		dontProxyHeaders.add("trailer");
59  		dontProxyHeaders.add("proxy-authorization");
60  		dontProxyHeaders.add("proxy-authenticate");
61  		dontProxyHeaders.add("upgrade");
62  	}
63  
64  	public ProxyServlet(SoapMonitor soapMonitor)
65  	{
66  		this.monitor = soapMonitor;
67  		this.project = monitor.getProject();
68  	}
69  
70  	public void destroy()
71  	{
72  	}
73  
74  	public ServletConfig getServletConfig()
75  	{
76  		return config;
77  	}
78  
79  	public String getServletInfo()
80  	{
81  		return "SoapUI Monitor";
82  	}
83  
84  	public void init(ServletConfig config) throws ServletException
85  	{
86  
87  		this.config = config;
88  		this.context = config.getServletContext();
89  
90  		client = new HttpClient();
91  		client.setConnectorType(HttpClient.CONNECTOR_SOCKET);// CONNECTOR_SELECT_CHANNEL);
92  		try
93  		{
94  			client.start();
95  		}
96  		catch (Exception e)
97  		{
98  			throw new ServletException(e);
99  		}
100 
101 	}
102 
103 	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException
104 	{
105 
106 		HttpServletRequest httpRequest = (HttpServletRequest) request;
107 		HttpServletResponse httpResponse = (HttpServletResponse) response;
108 
109 		if (capturedData == null)
110 		{
111 			capturedData = new JProxyServletWsdlMonitorMessageExchange(project);
112 			capturedData.setRequestHost(httpRequest.getServerName());
113 			capturedData.setTargetHost(httpRequest.getRemoteHost());
114 			capturedData.setRequestHeader(httpRequest);
115 		}
116 
117 		// if ("CONNECT".equalsIgnoreCase(httpRequest.getMethod()))
118 		// {
119 		// handleConnect(httpRequest,httpResponse);
120 		// }
121 		// else
122 		// {
123 		CaptureInputStream capture = new CaptureInputStream(httpRequest.getInputStream());
124 		Continuation continuation = ContinuationSupport.getContinuation(httpRequest, httpRequest);
125 
126 		if (!continuation.isPending())
127 		{
128 			String uri = httpRequest.getRequestURI();
129 			if (httpRequest.getQueryString() != null)
130 				uri += "?" + httpRequest.getQueryString();
131 
132 			SoapUIHttpExchange exchange = new SoapUIHttpExchange(monitor, httpRequest, httpResponse, capture, capturedData);
133 
134 			exchange.setScheme(HttpSchemes.HTTPS.equals(request.getScheme()) ? HttpSchemes.HTTPS_BUFFER
135 					: HttpSchemes.HTTP_BUFFER);
136 			exchange.setMethod(httpRequest.getMethod());
137 			exchange.setURI(uri);
138 			capturedData.setTargetURL(httpRequest.getRequestURL().toString());
139 
140 			exchange.setVersion(httpRequest.getProtocol());
141 			InetSocketAddress address = new InetSocketAddress(httpRequest.getServerName(), httpRequest.getServerPort());
142 			exchange.setAddress(address);
143 
144 			System.err.println("PROXY TO http://" + address.getHostName() + ":" + address.getPort() + uri);
145 
146 			// check connection header
147 			String connectionHeader = httpRequest.getHeader("Connection");
148 			if (connectionHeader != null)
149 			{
150 				connectionHeader = connectionHeader.toLowerCase();
151 				if (connectionHeader.indexOf("keep-alive") < 0 && connectionHeader.indexOf("close") < 0)
152 					connectionHeader = null;
153 			}
154 
155 			// copy headers
156 			boolean xForwardedFor = false;
157 			boolean hasContent = false;
158 			@SuppressWarnings("unused")
159 			long contentLength = -1;
160 			Enumeration headerNames = httpRequest.getHeaderNames();
161 			while (headerNames.hasMoreElements())
162 			{
163 				String hdr = (String) headerNames.nextElement();
164 				String lhdr = hdr.toLowerCase();
165 
166 				if (dontProxyHeaders.contains(lhdr))
167 					continue;
168 				if (connectionHeader != null && connectionHeader.indexOf(lhdr) >= 0)
169 					continue;
170 
171 				if ("content-type".equals(lhdr))
172 					hasContent = true;
173 				if ("content-length".equals(lhdr))
174 					contentLength = request.getContentLength();
175 
176 				Enumeration vals = httpRequest.getHeaders(hdr);
177 				while (vals.hasMoreElements())
178 				{
179 					String val = (String) vals.nextElement();
180 					if (val != null)
181 					{
182 						exchange.setRequestHeader(lhdr, val);
183 						xForwardedFor |= "X-Forwarded-For".equalsIgnoreCase(hdr);
184 					}
185 				}
186 			}
187 
188 			// Proxy headers
189 			exchange.setRequestHeader("Via", "SoapUI Monitor");
190 			if (!xForwardedFor)
191 				exchange.addRequestHeader("X-Forwarded-For", request.getRemoteAddr());
192 
193 			if (hasContent)
194 			{
195 				exchange.setRequestContentSource(capture);
196 			}
197 			client.send(exchange);
198 			continuation.suspend(3000);
199 		}
200 		// }
201 		// if operation is stoped clear it.
202 		if (!capturedData.isStopCapture())
203 		{
204 			// capturedData.discard();
205 			monitor.addMessageExchange(capturedData);
206 			System.err.println("Killed " + capturedData.toString());
207 			capturedData = null;
208 		}
209 	}
210 
211 
212 
213 	// public static void main(String[] args) throws Exception {
214 	//		
215 	// Server server = new Server();
216 	// SelectChannelConnector connector = new SelectChannelConnector();
217 	// connector.setPort(8888);
218 	// server.addConnector(connector);
219 	// Context context = new Context(server, "/", 0);
220 	// context.addServlet(new ServletHolder(new ProxyServlet()), "/");
221 	//		
222 	// server.start();
223 	// server.join();
224 	//		
225 	// }
226 
227 }