1
2
3
4
5
6
7
8
9
10
11
12 package com.eviware.soapui.impl.wsdl.monitor.jettyproxy;
13
14 import java.io.ByteArrayInputStream;
15 import java.io.ByteArrayOutputStream;
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.Enumeration;
19 import java.util.HashSet;
20 import java.util.List;
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.apache.commons.httpclient.Header;
32 import org.apache.commons.httpclient.HostConfiguration;
33 import org.apache.commons.httpclient.HttpState;
34 import org.apache.commons.httpclient.URI;
35 import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
36 import org.mortbay.util.IO;
37
38 import com.eviware.soapui.impl.wsdl.WsdlProject;
39 import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction;
40 import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm;
41 import com.eviware.soapui.impl.wsdl.monitor.CaptureInputStream;
42 import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange;
43 import com.eviware.soapui.impl.wsdl.monitor.SoapMonitor;
44 import com.eviware.soapui.impl.wsdl.submit.transports.http.ExtendedHttpMethod;
45 import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedGetMethod;
46 import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod;
47 import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
48 import com.eviware.soapui.model.settings.Settings;
49 import com.eviware.soapui.support.types.StringToStringsMap;
50
51 public class ProxyServlet implements Servlet
52 {
53 protected ServletConfig config;
54 protected ServletContext context;
55 protected SoapMonitor monitor;
56 protected WsdlProject project;
57 protected HttpState httpState = new HttpState();
58 protected Settings settings;
59
60 static HashSet<String> dontProxyHeaders = new HashSet<String>();
61 {
62 dontProxyHeaders.add( "proxy-connection" );
63 dontProxyHeaders.add( "connection" );
64 dontProxyHeaders.add( "keep-alive" );
65 dontProxyHeaders.add( "transfer-encoding" );
66 dontProxyHeaders.add( "te" );
67 dontProxyHeaders.add( "trailer" );
68 dontProxyHeaders.add( "proxy-authorization" );
69 dontProxyHeaders.add( "proxy-authenticate" );
70 dontProxyHeaders.add( "upgrade" );
71 }
72
73 public ProxyServlet( SoapMonitor soapMonitor )
74 {
75 this.monitor = soapMonitor;
76 this.project = monitor.getProject();
77 settings = project.getSettings();
78 }
79
80 public void destroy()
81 {
82 }
83
84 public ServletConfig getServletConfig()
85 {
86 return config;
87 }
88
89 public String getServletInfo()
90 {
91 return "SoapUI Monitor";
92 }
93
94 public void init( ServletConfig config ) throws ServletException
95 {
96 this.config = config;
97 this.context = config.getServletContext();
98 }
99
100 public void service( ServletRequest request, ServletResponse response ) throws ServletException, IOException
101 {
102 monitor.fireOnRequest( request, response );
103 if( response.isCommitted() )
104 return;
105
106 ExtendedHttpMethod method;
107 HttpServletRequest httpRequest = ( HttpServletRequest )request;
108 if( httpRequest.getMethod().equals( "GET" ) )
109 method = new ExtendedGetMethod();
110 else
111 method = new ExtendedPostMethod();
112
113 method.setDecompress( false );
114
115
116 JProxyServletWsdlMonitorMessageExchange capturedData = new JProxyServletWsdlMonitorMessageExchange( project );
117 capturedData.setRequestHost( httpRequest.getServerName() );
118 capturedData.setRequestMethod( httpRequest.getMethod() );
119 capturedData.setRequestHeader( httpRequest );
120 capturedData.setHttpRequestParameters( httpRequest );
121 capturedData.setTargetURL( httpRequest.getRequestURL().toString() );
122
123 CaptureInputStream capture = new CaptureInputStream( httpRequest.getInputStream() );
124
125
126 String connectionHeader = httpRequest.getHeader( "Connection" );
127 if( connectionHeader != null )
128 {
129 connectionHeader = connectionHeader.toLowerCase();
130 if( connectionHeader.indexOf( "keep-alive" ) < 0 && connectionHeader.indexOf( "close" ) < 0 )
131 connectionHeader = null;
132 }
133
134
135 boolean xForwardedFor = false;
136 @SuppressWarnings( "unused" )
137 long contentLength = -1;
138 Enumeration<?> headerNames = httpRequest.getHeaderNames();
139 while( headerNames.hasMoreElements() )
140 {
141 String hdr = ( String )headerNames.nextElement();
142 String lhdr = hdr.toLowerCase();
143
144 if( dontProxyHeaders.contains( lhdr ) )
145 continue;
146 if( connectionHeader != null && connectionHeader.indexOf( lhdr ) >= 0 )
147 continue;
148
149 if( "content-length".equals( lhdr ) )
150 contentLength = request.getContentLength();
151
152 Enumeration<?> vals = httpRequest.getHeaders( hdr );
153 while( vals.hasMoreElements() )
154 {
155 String val = ( String )vals.nextElement();
156 if( val != null )
157 {
158 method.setRequestHeader( lhdr, val );
159 xForwardedFor |= "X-Forwarded-For".equalsIgnoreCase( hdr );
160 }
161 }
162 }
163
164
165 method.setRequestHeader( "Via", "SoapUI Monitor" );
166 if( !xForwardedFor )
167 method.addRequestHeader( "X-Forwarded-For", request.getRemoteAddr() );
168
169 if( method instanceof ExtendedPostMethod )
170 ( ( ExtendedPostMethod )method ).setRequestEntity( new InputStreamRequestEntity( capture, request
171 .getContentType() ) );
172
173 HostConfiguration hostConfiguration = new HostConfiguration();
174
175 StringBuffer url = new StringBuffer( "http://" );
176 url.append( httpRequest.getServerName() );
177 if( httpRequest.getServerPort() != 80 )
178 url.append( ":" + httpRequest.getServerPort() );
179 if( httpRequest.getServletPath() != null )
180 {
181 url.append( httpRequest.getServletPath() );
182 method.setPath( httpRequest.getServletPath() );
183 if( httpRequest.getQueryString() != null )
184 {
185 url.append( "?" + httpRequest.getQueryString() );
186 method.setPath( httpRequest.getServletPath() + "?" + httpRequest.getQueryString() );
187 }
188 }
189 hostConfiguration.setHost( new URI( url.toString(), true ) );
190
191
192
193 monitor.fireBeforeProxy( request, response, method, hostConfiguration );
194
195 if( settings.getBoolean( LaunchForm.SSLTUNNEL_REUSESTATE ) )
196 {
197 if( httpState == null )
198 httpState = new HttpState();
199 HttpClientSupport.getHttpClient().executeMethod( hostConfiguration, method, httpState );
200 }
201 else
202 {
203 HttpClientSupport.getHttpClient().executeMethod( hostConfiguration, method );
204 }
205
206
207 capturedData.stopCapture();
208
209 capturedData.setRequest( capture.getCapturedData() );
210 capturedData.setRawResponseBody( method.getResponseBody() );
211 capturedData.setResponseHeader( method );
212 capturedData.setRawRequestData( getRequestToBytes( request.toString(), method, capture ) );
213 capturedData.setRawResponseData( getResponseToBytes( response.toString(), method, capturedData
214 .getRawResponseBody() ) );
215 capturedData.setResponseContent( new String( method.getDecompressedResponseBody() ) );
216
217 monitor.fireAfterProxy( request, response, method, capturedData );
218
219 if( !response.isCommitted() )
220 {
221 StringToStringsMap responseHeaders = capturedData.getResponseHeaders();
222
223
224
225 HttpServletResponse httpResponse = ( HttpServletResponse )response;
226 for( String name : responseHeaders.keySet() )
227 {
228 for( String header : responseHeaders.get( name ) )
229 httpResponse.addHeader( name, header );
230 }
231
232 IO.copy( new ByteArrayInputStream( capturedData.getRawResponseBody() ), httpResponse.getOutputStream() );
233 }
234
235 synchronized( this )
236 {
237 if( checkContentType( method ) )
238 {
239 monitor.addMessageExchange( capturedData );
240 }
241 }
242 }
243
244 private boolean checkContentType( ExtendedHttpMethod method )
245 {
246 String[] contentTypes = settings
247 .getString( LaunchForm.SET_CONTENT_TYPES, SoapMonitorAction.defaultContentTypes() ).split( "," );
248 List<String> contentTypelist = new ArrayList<String>();
249 for( String ct : contentTypes )
250 {
251 contentTypelist.add( ct.trim().replace( "*", "" ) );
252 }
253
254 Header[] headers = method.getResponseHeaders( "Content-Type" );
255 for( Header header : headers )
256 {
257 for( String contentType : contentTypelist )
258 {
259 if( header.getValue().indexOf( contentType ) > 0 )
260 {
261 return true;
262 }
263 }
264 }
265 return false;
266 }
267
268 private byte[] getResponseToBytes( String status, ExtendedHttpMethod postMethod, byte[] res )
269 {
270 String response = status.trim() + "\r\n";
271
272 Header[] headers = postMethod.getResponseHeaders();
273 for( Header header : headers )
274 {
275 response += header.toString().trim() + "\r\n";
276 }
277 response += "\r\n";
278
279 ByteArrayOutputStream out = new ByteArrayOutputStream();
280 try
281 {
282 out.write( response.getBytes() );
283 out.write( res );
284 }
285 catch( IOException e )
286 {
287 e.printStackTrace();
288 }
289 return out.toByteArray();
290 }
291
292 private byte[] getRequestToBytes( String footer, ExtendedHttpMethod postMethod, CaptureInputStream capture )
293 {
294 ByteArrayOutputStream out = new ByteArrayOutputStream();
295
296 try
297 {
298 out.write( footer.trim().getBytes() );
299 out.write( "\r\n\r\n".getBytes() );
300 out.write( capture.getCapturedData() );
301 }
302 catch( IOException e )
303 {
304 e.printStackTrace();
305 }
306
307 return out.toByteArray();
308 }
309
310 }