Java tutorial
/* * soapUI, copyright (C) 2004-2011 eviware.com * * soapUI is free software; you can redistribute it and/or modify it under the * terms of version 2.1 of the GNU Lesser General Public License as published by * the Free Software Foundation. * * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details at gnu.org. */ package com.eviware.soapui.impl.wsdl.monitor.jettyproxy; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HttpState; import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.methods.InputStreamRequestEntity; import org.mortbay.util.IO; import com.eviware.soapui.impl.wsdl.WsdlProject; import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction; import com.eviware.soapui.impl.wsdl.actions.monitor.SoapMonitorAction.LaunchForm; import com.eviware.soapui.impl.wsdl.monitor.CaptureInputStream; import com.eviware.soapui.impl.wsdl.monitor.JProxyServletWsdlMonitorMessageExchange; import com.eviware.soapui.impl.wsdl.monitor.SoapMonitor; 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.model.settings.Settings; import com.eviware.soapui.support.types.StringToStringsMap; public class ProxyServlet implements Servlet { protected ServletConfig config; protected ServletContext context; protected SoapMonitor monitor; protected WsdlProject project; protected HttpState httpState = new HttpState(); protected Settings settings; static HashSet<String> dontProxyHeaders = new HashSet<String>(); { dontProxyHeaders.add("proxy-connection"); dontProxyHeaders.add("connection"); dontProxyHeaders.add("keep-alive"); dontProxyHeaders.add("transfer-encoding"); dontProxyHeaders.add("te"); dontProxyHeaders.add("trailer"); dontProxyHeaders.add("proxy-authorization"); dontProxyHeaders.add("proxy-authenticate"); dontProxyHeaders.add("upgrade"); } public ProxyServlet(SoapMonitor soapMonitor) { this.monitor = soapMonitor; this.project = monitor.getProject(); settings = project.getSettings(); } public void destroy() { } public ServletConfig getServletConfig() { return config; } public String getServletInfo() { return "SoapUI Monitor"; } public void init(ServletConfig config) throws ServletException { this.config = config; this.context = config.getServletContext(); } public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { monitor.fireOnRequest(request, response); if (response.isCommitted()) return; ExtendedHttpMethod method; HttpServletRequest httpRequest = (HttpServletRequest) request; if (httpRequest.getMethod().equals("GET")) method = new ExtendedGetMethod(); else method = new ExtendedPostMethod(); method.setDecompress(false); // for this create ui server and port, properties. JProxyServletWsdlMonitorMessageExchange capturedData = new JProxyServletWsdlMonitorMessageExchange(project); capturedData.setRequestHost(httpRequest.getServerName()); capturedData.setRequestMethod(httpRequest.getMethod()); capturedData.setRequestHeader(httpRequest); capturedData.setHttpRequestParameters(httpRequest); capturedData.setTargetURL(httpRequest.getRequestURL().toString()); CaptureInputStream capture = new CaptureInputStream(httpRequest.getInputStream()); // check connection header String connectionHeader = httpRequest.getHeader("Connection"); if (connectionHeader != null) { connectionHeader = connectionHeader.toLowerCase(); if (connectionHeader.indexOf("keep-alive") < 0 && connectionHeader.indexOf("close") < 0) connectionHeader = null; } // copy headers boolean xForwardedFor = false; @SuppressWarnings("unused") long contentLength = -1; Enumeration<?> headerNames = httpRequest.getHeaderNames(); while (headerNames.hasMoreElements()) { String hdr = (String) headerNames.nextElement(); String lhdr = hdr.toLowerCase(); if (dontProxyHeaders.contains(lhdr)) continue; if (connectionHeader != null && connectionHeader.indexOf(lhdr) >= 0) continue; if ("content-length".equals(lhdr)) contentLength = request.getContentLength(); Enumeration<?> vals = httpRequest.getHeaders(hdr); while (vals.hasMoreElements()) { String val = (String) vals.nextElement(); if (val != null) { method.setRequestHeader(lhdr, val); xForwardedFor |= "X-Forwarded-For".equalsIgnoreCase(hdr); } } } // Proxy headers method.setRequestHeader("Via", "SoapUI Monitor"); if (!xForwardedFor) method.addRequestHeader("X-Forwarded-For", request.getRemoteAddr()); if (method instanceof ExtendedPostMethod) ((ExtendedPostMethod) method) .setRequestEntity(new InputStreamRequestEntity(capture, request.getContentType())); HostConfiguration hostConfiguration = new HostConfiguration(); StringBuffer url = new StringBuffer("http://"); url.append(httpRequest.getServerName()); if (httpRequest.getServerPort() != 80) url.append(":" + httpRequest.getServerPort()); if (httpRequest.getServletPath() != null) { url.append(httpRequest.getServletPath()); method.setPath(httpRequest.getServletPath()); if (httpRequest.getQueryString() != null) { url.append("?" + httpRequest.getQueryString()); method.setPath(httpRequest.getServletPath() + "?" + httpRequest.getQueryString()); } } hostConfiguration.setHost(new URI(url.toString(), true)); // SoapUI.log("PROXY to:" + url); monitor.fireBeforeProxy(request, response, method, hostConfiguration); if (settings.getBoolean(LaunchForm.SSLTUNNEL_REUSESTATE)) { if (httpState == null) httpState = new HttpState(); HttpClientSupport.getHttpClient().executeMethod(hostConfiguration, method, httpState); } else { HttpClientSupport.getHttpClient().executeMethod(hostConfiguration, method); } // wait for transaction to end and store it. capturedData.stopCapture(); capturedData.setRequest(capture.getCapturedData()); capturedData.setRawResponseBody(method.getResponseBody()); capturedData.setResponseHeader(method); capturedData.setRawRequestData(getRequestToBytes(request.toString(), method, capture)); capturedData.setRawResponseData( getResponseToBytes(response.toString(), method, capturedData.getRawResponseBody())); capturedData.setResponseContent(new String(method.getDecompressedResponseBody())); monitor.fireAfterProxy(request, response, method, capturedData); if (!response.isCommitted()) { StringToStringsMap responseHeaders = capturedData.getResponseHeaders(); // capturedData = null; // copy headers to response HttpServletResponse httpResponse = (HttpServletResponse) response; for (String name : responseHeaders.keySet()) { for (String header : responseHeaders.get(name)) httpResponse.addHeader(name, header); } IO.copy(new ByteArrayInputStream(capturedData.getRawResponseBody()), httpResponse.getOutputStream()); } synchronized (this) { if (checkContentType(method)) { monitor.addMessageExchange(capturedData); } } } private boolean checkContentType(ExtendedHttpMethod method) { String[] contentTypes = settings .getString(LaunchForm.SET_CONTENT_TYPES, SoapMonitorAction.defaultContentTypes()).split(","); List<String> contentTypelist = new ArrayList<String>(); for (String ct : contentTypes) { contentTypelist.add(ct.trim().replace("*", "")); } Header[] headers = method.getResponseHeaders("Content-Type"); for (Header header : headers) { for (String contentType : contentTypelist) { if (header.getValue().indexOf(contentType) > 0) { return true; } } } return false; } private byte[] getResponseToBytes(String status, ExtendedHttpMethod postMethod, byte[] res) { String response = status.trim() + "\r\n"; Header[] headers = postMethod.getResponseHeaders(); for (Header header : headers) { response += header.toString().trim() + "\r\n"; } response += "\r\n"; ByteArrayOutputStream out = new ByteArrayOutputStream(); try { out.write(response.getBytes()); out.write(res); } catch (IOException e) { e.printStackTrace(); } return out.toByteArray(); } private byte[] getRequestToBytes(String footer, ExtendedHttpMethod postMethod, CaptureInputStream capture) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { out.write(footer.trim().getBytes()); out.write("\r\n\r\n".getBytes()); out.write(capture.getCapturedData()); } catch (IOException e) { e.printStackTrace(); } return out.toByteArray(); } }