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.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 import javax.servlet.http.HttpServletResponse;
27
28 import org.apache.commons.httpclient.Header;
29 import org.apache.commons.httpclient.HostConfiguration;
30 import org.apache.commons.httpclient.HttpClient;
31 import org.apache.commons.httpclient.HttpMethodBase;
32 import org.apache.commons.httpclient.HttpState;
33 import org.apache.commons.httpclient.URI;
34 import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
35 import org.mortbay.util.IO;
36
37 import com.eviware.soapui.impl.wsdl.WsdlProject;
38 import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm;
39 import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange;
40 import com.eviware.soapui.impl.wsdl.monitor.SoapMonitor;
41 import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedGetMethod;
42 import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod;
43 import com.eviware.soapui.model.settings.Settings;
44 import com.eviware.soapui.support.types.StringToStringMap;
45 import com.eviware.soapui.support.xml.XmlUtils;
46
47 public class ProxyServlet implements Servlet
48 {
49
50 protected ServletConfig config;
51 protected ServletContext context;
52 protected HttpClient client;
53 protected SoapMonitor monitor;
54 protected WsdlProject project;
55 protected HttpState httpState = new HttpState();
56 protected Settings settings;
57
58 static HashSet<String> dontProxyHeaders = new HashSet<String>();
59 {
60 dontProxyHeaders.add( "proxy-connection" );
61 dontProxyHeaders.add( "connection" );
62 dontProxyHeaders.add( "keep-alive" );
63 dontProxyHeaders.add( "transfer-encoding" );
64 dontProxyHeaders.add( "te" );
65 dontProxyHeaders.add( "trailer" );
66 dontProxyHeaders.add( "proxy-authorization" );
67 dontProxyHeaders.add( "proxy-authenticate" );
68 dontProxyHeaders.add( "upgrade" );
69 }
70
71 public ProxyServlet( SoapMonitor soapMonitor )
72 {
73 this.monitor = soapMonitor;
74 this.project = monitor.getProject();
75 settings = project.getSettings();
76 }
77
78 public void destroy()
79 {
80 }
81
82 public ServletConfig getServletConfig()
83 {
84 return config;
85 }
86
87 public String getServletInfo()
88 {
89 return "SoapUI Monitor";
90 }
91
92 public void init( ServletConfig config ) throws ServletException
93 {
94
95 this.config = config;
96 this.context = config.getServletContext();
97
98 client = new HttpClient();
99
100 }
101
102 public synchronized void service( ServletRequest request, ServletResponse response ) throws ServletException,
103 IOException
104 {
105 monitor.fireOnRequest( request, response );
106 if( response.isCommitted() )
107 return;
108
109 HttpMethodBase method;
110 HttpServletRequest httpRequest = ( HttpServletRequest )request;
111 if( httpRequest.getMethod().equals( "GET" ) )
112 method = new ExtendedGetMethod();
113 else
114 method = new ExtendedPostMethod();
115
116
117 JProxyServletWsdlMonitorMessageExchange capturedData = new JProxyServletWsdlMonitorMessageExchange( project );
118 capturedData.setRequestHost( httpRequest.getServerName() );
119 capturedData.setRequestHeader( httpRequest );
120 capturedData.setTargetURL( httpRequest.getRequestURL().toString() );
121
122 CaptureInputStream capture = new CaptureInputStream( httpRequest.getInputStream() );
123
124
125 String connectionHeader = httpRequest.getHeader( "Connection" );
126 if( connectionHeader != null )
127 {
128 connectionHeader = connectionHeader.toLowerCase();
129 if( connectionHeader.indexOf( "keep-alive" ) < 0 && connectionHeader.indexOf( "close" ) < 0 )
130 connectionHeader = null;
131 }
132
133
134 boolean xForwardedFor = false;
135 @SuppressWarnings( "unused" )
136 long contentLength = -1;
137 Enumeration<?> headerNames = httpRequest.getHeaderNames();
138 while( headerNames.hasMoreElements() )
139 {
140 String hdr = ( String )headerNames.nextElement();
141 String lhdr = hdr.toLowerCase();
142
143 if( dontProxyHeaders.contains( lhdr ) )
144 continue;
145 if( connectionHeader != null && connectionHeader.indexOf( lhdr ) >= 0 )
146 continue;
147
148 if( "content-length".equals( lhdr ) )
149 contentLength = request.getContentLength();
150
151 Enumeration<?> vals = httpRequest.getHeaders( hdr );
152 while( vals.hasMoreElements() )
153 {
154 String val = ( String )vals.nextElement();
155 if( val != null )
156 {
157 method.setRequestHeader( lhdr, val );
158 xForwardedFor |= "X-Forwarded-For".equalsIgnoreCase( hdr );
159 }
160 }
161 }
162
163
164 method.setRequestHeader( "Via", "SoapUI Monitor" );
165 if( !xForwardedFor )
166 method.addRequestHeader( "X-Forwarded-For", request.getRemoteAddr() );
167
168 if( method instanceof ExtendedPostMethod )
169 ( ( ExtendedPostMethod )method ).setRequestEntity( new InputStreamRequestEntity( capture, request
170 .getContentType() ) );
171
172 HostConfiguration hostConfiguration = new HostConfiguration();
173
174 StringBuffer url = new StringBuffer( "http://" );
175 url.append( httpRequest.getServerName() );
176 if( httpRequest.getServerPort() != 80 )
177 url.append( ":" + httpRequest.getServerPort() );
178 if( httpRequest.getServletPath() != null )
179 {
180 url.append( httpRequest.getServletPath() );
181 method.setPath( httpRequest.getServletPath() );
182 if( httpRequest.getQueryString() != null )
183 {
184 url.append( "?" + httpRequest.getQueryString() );
185 method.setPath( httpRequest.getServletPath() + "?" + httpRequest.getQueryString() );
186 }
187 }
188 hostConfiguration.setHost( new URI( url.toString(), true ) );
189
190
191
192 monitor.fireBeforeProxy( request, response, method, hostConfiguration );
193
194 if( settings.getBoolean( LaunchForm.SSLTUNNEL_REUSESTATE ) )
195 {
196 if( httpState == null )
197 httpState = new HttpState();
198 client.executeMethod( hostConfiguration, method, httpState );
199 }
200 else
201 {
202 client.executeMethod( hostConfiguration, method );
203 }
204
205
206 capturedData.stopCapture();
207
208 capturedData.setRequest( capture.getCapturedData() );
209 capturedData.setRawResponseBody( method.getResponseBody() );
210 capturedData.setResponseHeader( method );
211 capturedData.setRawRequestData( getRequestToBytes( request.toString(), method, capture ) );
212 capturedData.setRawResponseData( getResponseToBytes( response.toString(), method, capturedData
213 .getRawResponseBody() ) );
214
215 monitor.fireAfterProxy( request, response, method, capturedData );
216
217 if( !response.isCommitted() )
218 {
219 StringToStringMap responseHeaders = capturedData.getResponseHeaders();
220
221
222
223 HttpServletResponse httpResponse = ( HttpServletResponse )response;
224 for( String name : responseHeaders.keySet() )
225 {
226 String header = responseHeaders.get( name );
227 if( !httpResponse.containsHeader( name ) )
228 httpResponse.addHeader( name, header );
229 }
230
231 IO.copy( new ByteArrayInputStream( capturedData.getRawResponseBody() ), httpResponse.getOutputStream() );
232 }
233
234 monitor.addMessageExchange( capturedData );
235 }
236
237 private byte[] getResponseToBytes( String footer, HttpMethodBase postMethod, byte[] res )
238 {
239 String response = footer;
240
241 Header[] headers = postMethod.getResponseHeaders();
242 for( Header header : headers )
243 {
244 response += header.toString();
245 }
246 response += "\n";
247 response += XmlUtils.prettyPrintXml( new String( res ) );
248
249 return response.getBytes();
250 }
251
252 private byte[] getRequestToBytes( String footer, HttpMethodBase postMethod, CaptureInputStream capture )
253 {
254 String request = footer;
255
256
257
258
259
260
261 request += "\n";
262 request += XmlUtils.prettyPrintXml( new String( capture.getCapturedData() ) );
263
264 return request.getBytes();
265 }
266
267 }