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