/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.wsdl.monitor.jettyproxy; import com.eviware.soapui.SoapUI; import com.eviware.soapui.impl.wsdl.WsdlProject; import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm; import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.SecurityTabForm; import com.eviware.soapui.impl.wsdl.monitor.CaptureInputStream; import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange; import com.eviware.soapui.impl.wsdl.monitor.SoapMonitorListenerCallBack; import com.eviware.soapui.impl.wsdl.submit.transports.http.ExtendedHttpMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedGetMethod; import com.eviware.soapui.impl.wsdl.submit.transports.http.support.methods.ExtendedPostMethod; import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport; import com.eviware.soapui.impl.wsdl.support.http.SoapUIHttpRoute; import com.eviware.soapui.support.types.StringToStringsMap; import com.eviware.soapui.support.xml.XmlUtils; import org.apache.http.Header; import org.apache.http.client.utils.URIUtils; import org.apache.http.entity.InputStreamEntity; import org.apache.http.protocol.BasicHttpContext; import org.mortbay.util.IO; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.URISyntaxException; import java.util.Enumeration; import java.util.List; import java.util.Map; public class TunnelServlet extends ProxyServlet { private String sslEndPoint; private int sslPort = 443; private String prot = "https://"; public TunnelServlet(WsdlProject project, String sslEndpoint, SoapMonitorListenerCallBack listenerCallBack) { super(project, listenerCallBack); if (!sslEndpoint.startsWith("https")) { this.prot = "http://"; } int prefix = sslEndpoint.indexOf("://"); int c = sslEndpoint.indexOf(prefix, ':'); if (c > 0) { this.sslPort = Integer.parseInt(sslEndpoint.substring(c + 1)); this.sslEndPoint = sslEndpoint.substring(prefix, c); } else { if (prefix > 0) { this.sslEndPoint = sslEndpoint.substring(prefix + 3); } } } @Override public void init(ServletConfig config) throws ServletException { this.config = config; this.context = config.getServletContext(); } public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { listenerCallBack.fireOnRequest(project, request, response); if (response.isCommitted()) { return; } ExtendedHttpMethod postMethod; // for this create ui server and port, properties. InetSocketAddress inetAddress = new InetSocketAddress(sslEndPoint, sslPort); HttpServletRequest httpRequest = (HttpServletRequest) request; if (httpRequest.getMethod().equals("GET")) { postMethod = new ExtendedGetMethod(); } else { postMethod = new ExtendedPostMethod(); } JProxyServletWsdlMonitorMessageExchange capturedData = new JProxyServletWsdlMonitorMessageExchange(project); capturedData.setRequestHost(httpRequest.getRemoteHost()); capturedData.setRequestHeader(httpRequest); capturedData.setHttpRequestParameters(httpRequest); capturedData.setTargetURL(this.prot + inetAddress.getHostName()); CaptureInputStream capture = new CaptureInputStream(httpRequest.getInputStream()); long contentLength = -1; // copy headers Enumeration<?> headerNames = httpRequest.getHeaderNames(); while (headerNames.hasMoreElements()) { String hdr = (String) headerNames.nextElement(); String lhdr = hdr.toLowerCase(); if ("content-length".equals(lhdr)) { String val = httpRequest.getHeader(hdr); contentLength = Long.parseLong(val); continue; } if ("transfer-encoding".equals(lhdr)) { continue; } if ("host".equals(lhdr)) { Enumeration<?> vals = httpRequest.getHeaders(hdr); while (vals.hasMoreElements()) { String val = (String) vals.nextElement(); if (val.startsWith("127.0.0.1")) { postMethod.addHeader(hdr, sslEndPoint); } } continue; } Enumeration<?> vals = httpRequest.getHeaders(hdr); while (vals.hasMoreElements()) { String val = (String) vals.nextElement(); if (val != null) { postMethod.addHeader(hdr, val); } } } if (postMethod instanceof ExtendedPostMethod) { InputStreamEntity entity = new InputStreamEntity(capture, contentLength); entity.setContentType(request.getContentType()); ((ExtendedPostMethod) postMethod).setEntity(entity); } java.net.URI uri = null; try { uri = new java.net.URI(this.prot + sslEndPoint); } catch (URISyntaxException e) { SoapUI.logError(e); } postMethod.getParams().setParameter( SoapUIHttpRoute.SOAPUI_SSL_CONFIG, settings.getString(SecurityTabForm.SSLTUNNEL_KEYSTOREPATH, "") + " " + settings.getString(SecurityTabForm.SSLTUNNEL_KEYSTOREPASSWORD, "")); setProtocolversion(postMethod, request.getProtocol()); String path = null; if (!sslEndPoint.contains("/")) { path = "/"; } else { path = sslEndPoint.substring(sslEndPoint.indexOf("/"), sslEndPoint.length()); } if (uri != null) { try { postMethod.setURI(URIUtils.createURI(uri.getScheme(), uri.getHost(), uri.getPort(), path, uri.getQuery(), uri.getFragment())); } catch (URISyntaxException e) { SoapUI.logError(e); } } listenerCallBack.fireBeforeProxy(project, request, response, postMethod); if (settings.getBoolean(LaunchForm.SSLTUNNEL_REUSESTATE)) { if (httpState == null) { httpState = new BasicHttpContext(); } HttpClientSupport.execute(postMethod, httpState); } else { HttpClientSupport.execute(postMethod); } capturedData.stopCapture(); capturedData.setRequest(capture.getCapturedData()); capturedData.setRawResponseBody(postMethod.getResponseBody()); capturedData.setResponseHeader(postMethod.getHttpResponse()); capturedData.setRawRequestData(getRequestToBytes(request.toString(), postMethod, capture)); capturedData.setRawResponseData(getResponseToBytes(response.toString(), postMethod, capturedData.getRawResponseBody())); listenerCallBack.fireAfterProxy(project, request, response, postMethod, capturedData); StringToStringsMap responseHeaders = capturedData.getResponseHeaders(); // copy headers to response HttpServletResponse httpServletResponse = (HttpServletResponse) response; for (Map.Entry<String, List<String>> headerEntry : responseHeaders.entrySet()) { for (String header : headerEntry.getValue()) { httpServletResponse.addHeader(headerEntry.getKey(), header); } } IO.copy(new ByteArrayInputStream(capturedData.getRawResponseBody()), httpServletResponse.getOutputStream()); synchronized (this) { listenerCallBack.fireAddMessageExchange(capturedData); } } private byte[] getResponseToBytes(String footer, ExtendedHttpMethod postMethod, byte[] res) { String response = footer; if (postMethod.hasHttpResponse()) { Header[] headers = postMethod.getHttpResponse().getAllHeaders(); for (Header header : headers) { response += header.toString().trim() + "\n"; } response += "\n"; response += XmlUtils.prettyPrintXml(new String(res)); } return response.getBytes(); } private byte[] getRequestToBytes(String footer, ExtendedHttpMethod postMethod, CaptureInputStream capture) { String request = footer; // Header[] headers = postMethod.getRequestHeaders(); // for (Header header : headers) // { // request += header.toString(); // } request += "\n"; request += XmlUtils.prettyPrintXml(new String(capture.getCapturedData())); return request.getBytes(); } }