View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 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.net.InetSocketAddress;
17  import java.util.Enumeration;
18  
19  import javax.servlet.ServletConfig;
20  import javax.servlet.ServletException;
21  import javax.servlet.ServletRequest;
22  import javax.servlet.ServletResponse;
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletResponse;
25  
26  import org.apache.commons.httpclient.Header;
27  import org.apache.commons.httpclient.HostConfiguration;
28  import org.apache.commons.httpclient.HttpMethodBase;
29  import org.apache.commons.httpclient.HttpState;
30  import org.apache.commons.httpclient.URI;
31  import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
32  import org.mortbay.util.IO;
33  
34  import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm;
35  import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange;
36  import com.eviware.soapui.impl.wsdl.monitor.SoapMonitor;
37  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedGetMethod;
38  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod;
39  import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
40  import com.eviware.soapui.impl.wsdl.support.http.SoapUIHostConfiguration;
41  import com.eviware.soapui.support.types.StringToStringMap;
42  import com.eviware.soapui.support.xml.XmlUtils;
43  
44  public class TunnelServlet extends ProxyServlet
45  {
46  
47  	private String sslEndPoint;
48  	private int sslPort = 443;
49  	private String prot = "https://";
50  
51  	public TunnelServlet( SoapMonitor soapMonitor, String sslEndpoint )
52  	{
53  		super( soapMonitor );
54  
55  		if( !sslEndpoint.startsWith( "https" ) )
56  		{
57  			this.prot = "http://";
58  		}
59  		int prefix = sslEndpoint.indexOf( "://" );
60  		int c = sslEndpoint.indexOf( prefix, ':' );
61  		if( c > 0 )
62  		{
63  			this.sslPort = Integer.parseInt( sslEndpoint.substring( c + 1 ) );
64  			this.sslEndPoint = sslEndpoint.substring( prefix, c );
65  		}
66  		else
67  		{
68  			if( prefix > 0 )
69  				this.sslEndPoint = sslEndpoint.substring( prefix + 3 );
70  		}
71  	}
72  
73  	@Override
74  	public void init( ServletConfig config ) throws ServletException
75  	{
76  		this.config = config;
77  		this.context = config.getServletContext();
78  
79  		client = HttpClientSupport.getHttpClient();
80  	}
81  
82  	public void service( ServletRequest request, ServletResponse response ) throws ServletException, IOException
83  	{
84  		monitor.fireOnRequest( request, response );
85  		if( response.isCommitted() )
86  			return;
87  
88  		HttpMethodBase postMethod;
89  
90  		// for this create ui server and port, properties.
91  		InetSocketAddress inetAddress = new InetSocketAddress( sslEndPoint, sslPort );
92  		HttpServletRequest httpRequest = ( HttpServletRequest )request;
93  		if( httpRequest.getMethod().equals( "GET" ) )
94  			postMethod = new ExtendedGetMethod();
95  		else
96  			postMethod = new ExtendedPostMethod();
97  
98  		if( capturedData == null )
99  		{
100 			capturedData = new JProxyServletWsdlMonitorMessageExchange( project );
101 			capturedData.setRequestHost( httpRequest.getRemoteHost() );
102 			capturedData.setRequestHeader( httpRequest );
103 			capturedData.setTargetURL( this.prot + inetAddress.getHostName() );
104 		}
105 
106 		CaptureInputStream capture = new CaptureInputStream( httpRequest.getInputStream() );
107 
108 		// copy headers
109 		Enumeration<?> headerNames = httpRequest.getHeaderNames();
110 		while( headerNames.hasMoreElements() )
111 		{
112 			String hdr = ( String )headerNames.nextElement();
113 			String lhdr = hdr.toLowerCase();
114 
115 			if( "host".equals( lhdr ) )
116 			{
117 				Enumeration<?> vals = httpRequest.getHeaders( hdr );
118 				while( vals.hasMoreElements() )
119 				{
120 					String val = ( String )vals.nextElement();
121 					if( val.startsWith( "127.0.0.1" ) )
122 					{
123 						postMethod.addRequestHeader( hdr, sslEndPoint );
124 					}
125 				}
126 				continue;
127 			}
128 
129 			Enumeration<?> vals = httpRequest.getHeaders( hdr );
130 			while( vals.hasMoreElements() )
131 			{
132 				String val = ( String )vals.nextElement();
133 				if( val != null )
134 				{
135 					postMethod.addRequestHeader( hdr, val );
136 				}
137 			}
138 
139 		}
140 
141 		if( postMethod instanceof ExtendedPostMethod )
142 			( ( ExtendedPostMethod )postMethod ).setRequestEntity( new InputStreamRequestEntity( capture,
143 					 request.getContentType() ) );
144 
145 		HostConfiguration hostConfiguration = new HostConfiguration();
146 
147 		httpRequest.getProtocol();
148 		hostConfiguration.getParams().setParameter(
149 				SoapUIHostConfiguration.SOAPUI_SSL_CONFIG,
150 				settings.getString( LaunchForm.SSLTUNNEL_KEYSTOREPATH, "" ) + " "
151 						+ settings.getString( LaunchForm.SSLTUNNEL_KEYSTOREPASSWORD, "" ) );
152 		hostConfiguration.setHost( new URI( this.prot + sslEndPoint, true ) );
153 
154 		postMethod.setPath( sslEndPoint.substring( sslEndPoint.indexOf( "/" ), sslEndPoint.length() ) );
155 
156 		monitor.fireBeforeProxy( request, response, postMethod, hostConfiguration );
157 
158 		if( settings.getBoolean( LaunchForm.SSLTUNNEL_REUSESTATE ) )
159 		{
160 			if( httpState == null )
161 				httpState = new HttpState();
162 			client.executeMethod( hostConfiguration, postMethod, httpState );
163 		}
164 		else
165 		{
166 			client.executeMethod( hostConfiguration, postMethod );
167 		}
168 		capturedData.stopCapture();
169 
170 		capturedData.setRequest( capture.getCapturedData() );
171 		capturedData.setRawResponseBody( postMethod.getResponseBody() );
172 		capturedData.setResponseHeader( postMethod );
173 		capturedData.setRawRequestData( getRequestToBytes( request.toString(), postMethod, capture ) );
174 		capturedData.setRawResponseData( getResponseToBytes( response.toString(), postMethod, capturedData
175 				.getRawResponseBody() ) );
176 
177 		monitor.fireAfterProxy( request, response, postMethod, capturedData );
178 
179 		StringToStringMap responseHeaders = capturedData.getResponseHeaders();
180 		capturedData = null;
181 		// copy headers to response
182 		HttpServletResponse httpResponse = ( HttpServletResponse )response;
183 		for( String name : responseHeaders.keySet() )
184 		{
185 			String header = responseHeaders.get( name );
186 			httpResponse.addHeader( name, header );
187 
188 		}
189 
190 		IO.copy( new ByteArrayInputStream( capturedData.getRawResponseBody() ), httpResponse.getOutputStream() );
191 
192 		postMethod.releaseConnection();
193 
194 		monitor.addMessageExchange( capturedData );
195 
196 	}
197 
198 	private byte[] getResponseToBytes( String footer, HttpMethodBase postMethod, byte[] res )
199 	{
200 		String response = footer;
201 
202 		Header[] headers = postMethod.getResponseHeaders();
203 		for( Header header : headers )
204 		{
205 			response += header.toString();
206 		}
207 		response += "\n";
208 		response += XmlUtils.prettyPrintXml( new String( res ) );
209 
210 		return response.getBytes();
211 	}
212 
213 	private byte[] getRequestToBytes( String footer, HttpMethodBase postMethod, CaptureInputStream capture )
214 	{
215 		String request = footer;
216 
217 		// Header[] headers = postMethod.getRequestHeaders();
218 		// for (Header header : headers)
219 		// {
220 		// request += header.toString();
221 		// }
222 		request += "\n";
223 		request += XmlUtils.prettyPrintXml( new String( capture.getCapturedData() ) );
224 
225 		return request.getBytes();
226 	}
227 
228 }