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.ByteArrayInputStream;
15  import java.io.IOException;
16  import java.util.Enumeration;
17  import java.util.HashSet;
18  
19  import javax.servlet.Servlet;
20  import javax.servlet.ServletConfig;
21  import javax.servlet.ServletContext;
22  import javax.servlet.ServletException;
23  import javax.servlet.ServletRequest;
24  import javax.servlet.ServletResponse;
25  import javax.servlet.http.HttpServletRequest;
26  
27  import org.apache.commons.httpclient.Header;
28  import org.apache.commons.httpclient.HostConfiguration;
29  import org.apache.commons.httpclient.HttpClient;
30  import org.apache.commons.httpclient.HttpState;
31  import org.apache.commons.httpclient.URI;
32  import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
33  import org.mortbay.util.IO;
34  
35  import com.eviware.soapui.impl.wsdl.WsdlProject;
36  import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm;
37  import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange;
38  import com.eviware.soapui.impl.wsdl.monitor.SoapMonitor;
39  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod;
40  import com.eviware.soapui.model.settings.Settings;
41  
42  public class ProxyServlet implements Servlet
43  {
44  
45  	protected ServletConfig config;
46  	protected ServletContext context;
47  	protected HttpClient client;
48  	protected JProxyServletWsdlMonitorMessageExchange capturedData;
49  	protected SoapMonitor monitor;
50  	protected WsdlProject project;
51  	protected HttpState httpState = null;
52  	protected Settings settings;
53  
54  	static HashSet<String> dontProxyHeaders = new HashSet<String>();
55  	{
56  		dontProxyHeaders.add("proxy-connection");
57  		dontProxyHeaders.add("connection");
58  		dontProxyHeaders.add("keep-alive");
59  		dontProxyHeaders.add("transfer-encoding");
60  		dontProxyHeaders.add("te");
61  		dontProxyHeaders.add("trailer");
62  		dontProxyHeaders.add("proxy-authorization");
63  		dontProxyHeaders.add("proxy-authenticate");
64  		dontProxyHeaders.add("upgrade");
65  	}
66  
67  	public ProxyServlet(SoapMonitor soapMonitor)
68  	{
69  		this.monitor = soapMonitor;
70  		this.project = monitor.getProject();
71  		settings = project.getSettings();
72  	}
73  
74  	public void destroy()
75  	{
76  	}
77  
78  	public ServletConfig getServletConfig()
79  	{
80  		return config;
81  	}
82  
83  	public String getServletInfo()
84  	{
85  		return "SoapUI Monitor";
86  	}
87  
88  	public void init(ServletConfig config) throws ServletException
89  	{
90  
91  		this.config = config;
92  		this.context = config.getServletContext();
93  
94  		client = new HttpClient();
95  
96  	}
97  
98  	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException
99  	{
100 
101 		HttpServletRequest httpRequest = (HttpServletRequest) request;
102 
103 		// for this create ui server and port, properties.
104 		ExtendedPostMethod postMethod = new ExtendedPostMethod();
105 
106 		if (capturedData == null)
107 		{
108 			capturedData = new JProxyServletWsdlMonitorMessageExchange(project);
109 			capturedData.setRequestHost(httpRequest.getServerName());
110 			capturedData.setRequestHeader(httpRequest);
111 			capturedData.setTargetURL(httpRequest.getRequestURL().toString());
112 		}
113 
114 		CaptureInputStream capture = new CaptureInputStream(httpRequest.getInputStream());
115 
116 		// check connection header
117 		String connectionHeader = httpRequest.getHeader("Connection");
118 		if (connectionHeader != null)
119 		{
120 			connectionHeader = connectionHeader.toLowerCase();
121 			if (connectionHeader.indexOf("keep-alive") < 0 && connectionHeader.indexOf("close") < 0)
122 				connectionHeader = null;
123 		}
124 
125 		// copy headers
126 		boolean xForwardedFor = false;
127 		@SuppressWarnings("unused")
128 		long contentLength = -1;
129 		Enumeration<?> headerNames = httpRequest.getHeaderNames();
130 		while (headerNames.hasMoreElements())
131 		{
132 			String hdr = (String) headerNames.nextElement();
133 			String lhdr = hdr.toLowerCase();
134 
135 			if (dontProxyHeaders.contains(lhdr))
136 				continue;
137 			if (connectionHeader != null && connectionHeader.indexOf(lhdr) >= 0)
138 				continue;
139 
140 			if ("content-length".equals(lhdr))
141 				contentLength = request.getContentLength();
142 
143 			Enumeration<?> vals = httpRequest.getHeaders(hdr);
144 			while (vals.hasMoreElements())
145 			{
146 				String val = (String) vals.nextElement();
147 				if (val != null)
148 				{
149 					postMethod.setRequestHeader(lhdr, val);
150 					xForwardedFor |= "X-Forwarded-For".equalsIgnoreCase(hdr);
151 				}
152 			}
153 		}
154 
155 		// Proxy headers
156 		postMethod.setRequestHeader("Via", "SoapUI Monitor");
157 		if (!xForwardedFor)
158 			postMethod.addRequestHeader("X-Forwarded-For", request.getRemoteAddr());
159 
160 		postMethod.setRequestEntity(new InputStreamRequestEntity(capture, "text/xml; charset=utf-8"));
161 		
162 		HostConfiguration hostConfiguration = new HostConfiguration();
163 		hostConfiguration.setHost(new URI("http://"+httpRequest.getServerName()+httpRequest.getServletPath(), true));
164 		postMethod.setPath("http://"+httpRequest.getServerName()+httpRequest.getServletPath());
165 		
166 		if (settings.getBoolean(LaunchForm.SSLTUNNEL_REUSESTATE))
167 		{
168 			if ( httpState == null ) 
169 				httpState = new HttpState();
170 			client.executeMethod(hostConfiguration, postMethod, httpState);
171 		}
172 		else
173 		{
174 			client.executeMethod(hostConfiguration, postMethod);
175 		}
176 		
177 		// wait for transaction to end and store it.
178 		capturedData.stopCapture();
179 		byte[] res = postMethod.getResponseBody();
180 		IO.copy(new ByteArrayInputStream(postMethod.getResponseBody()), response.getOutputStream());
181 		capturedData.setRequest(capture.getCapturedData());
182 		capturedData.setResponse(res);
183 		capturedData.setResponseHeader(postMethod);
184 		capturedData.setRawRequestData(getRequestToBytes(postMethod, capture));
185 		capturedData.setRawResponseData(getResponseToBytes(postMethod, res));
186 		monitor.addMessageExchange(capturedData);
187 		capturedData = null;
188 
189 		postMethod.releaseConnection();
190 	}
191 
192 
193 	private byte[] getResponseToBytes(ExtendedPostMethod postMethod, byte[] res)
194 	{
195 		String response = "";
196 
197 		Header[] headers = postMethod.getResponseHeaders();
198 		for (Header header : headers)
199 		{
200 			response += header.toString();
201 		}
202 		response += "\n";
203 		response += new String(res);
204 
205 		return response.getBytes();
206 	}
207 
208 	private byte[] getRequestToBytes(ExtendedPostMethod postMethod, CaptureInputStream capture)
209 	{
210 		String request = "";
211 
212 		Header[] headers = postMethod.getRequestHeaders();
213 		for (Header header : headers)
214 		{
215 			request += header.toString();
216 		}
217 		request += "\n";
218 		request += new String(capture.getCapturedData());
219 
220 		return request.getBytes();
221 	}
222 
223 }