// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.httpmonitor.proxy; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.util.Iterator; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.api.ContentProvider; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.proxy.ProxyServlet; import de.ugoe.cs.autoquest.httpmonitor.exchange.Status; import de.ugoe.cs.util.console.Console; /** *

* TODO document * the servlet deployed in the web server that receives all client messages and returns the client * java script. The messages are parsed, validated, and forwarded to the provided message listener. * If a message is not valid, it is discarded. If an event in a message is not valid, it is * discarded. Messages are only received via the POST HTTP method. The GET HTTP method is only * implemented for returning the client java script. *

* * @author Patrick Harms */ class HttpMonitoringProxyServlet extends ProxyServlet { /** */ private static final long serialVersionUID = 1L; /** */ private String proxiedServer; /** */ private int proxiedPort; /** */ private ExchangeListenerManager exchangeListenerManager; /** *

* initializes the servlet with the message listener to which all events shall be forwarded *

* * @param messageListener the message listener that shall receive all client events */ HttpMonitoringProxyServlet(String proxiedServer, int proxiedPort, ExchangeListenerManager exchangeListenerManager) { this.proxiedServer = proxiedServer; this.proxiedPort = proxiedPort; this.exchangeListenerManager = exchangeListenerManager; } /* (non-Javadoc) * @see org.eclipse.jetty.proxy.ProxyServlet#rewriteURI(javax.servlet.http.HttpServletRequest) */ @Override protected URI rewriteURI(HttpServletRequest request) { try { return new URI(request.getScheme(), null, proxiedServer, proxiedPort, request.getPathTranslated(), request.getQueryString(), null); } catch (URISyntaxException e) { Console.printerrln("could not rewrite URI: " + e); Console.logException(e); return null; } } /* (non-Javadoc) * @see org.eclipse.jetty.proxy.ProxyServlet#customizeProxyRequest(org.eclipse.jetty.client.api.Request, javax.servlet.http.HttpServletRequest) */ @Override protected void customizeProxyRequest(Request proxyRequest, HttpServletRequest request) { super.customizeProxyRequest(proxyRequest, request); exchangeListenerManager.onRequest(request); proxyRequest.content(new DubbingContentProvider(request, proxyRequest.getContent())); } /* (non-Javadoc) * @see org.eclipse.jetty.proxy.ProxyServlet#onResponseContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.eclipse.jetty.client.api.Response, byte[], int, int) */ @Override protected void onResponseContent(HttpServletRequest request, HttpServletResponse response, Response proxyResponse, byte[] buffer, int offset, int length) throws IOException { super.onResponseContent(request, response, proxyResponse, buffer, offset, length); exchangeListenerManager.onResponseContent(request, ByteBuffer.wrap(buffer, offset, length)); } /* (non-Javadoc) * @see org.eclipse.jetty.proxy.ProxyServlet#onResponseSuccess(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.eclipse.jetty.client.api.Response) */ @Override protected void onResponseSuccess(HttpServletRequest request, HttpServletResponse response, Response proxyResponse) { exchangeListenerManager.onResponse(request, response); exchangeListenerManager.onFinish(request, Status.SUCCESS); super.onResponseSuccess(request, response, proxyResponse); } /* (non-Javadoc) * @see org.eclipse.jetty.proxy.ProxyServlet#onResponseFailure(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.eclipse.jetty.client.api.Response, java.lang.Throwable) */ @Override protected void onResponseFailure(HttpServletRequest request, HttpServletResponse response, Response proxyResponse, Throwable failure) { exchangeListenerManager.onResponse(request, response); exchangeListenerManager.onFinish(request, Status.FAILURE); super.onResponseFailure(request, response, proxyResponse, failure); } /** * */ private class DubbingContentProvider implements ContentProvider { /** */ private HttpServletRequest request; /** */ private ContentProvider delegate; /** * */ public DubbingContentProvider(HttpServletRequest request, ContentProvider delegate) { this.request = request; this.delegate = delegate; } /* (non-Javadoc) * @see java.lang.Iterable#iterator() */ @Override public Iterator iterator() { return new DubbingByteBufferIterator(request, delegate.iterator()); } /* (non-Javadoc) * @see org.eclipse.jetty.client.api.ContentProvider#getLength() */ @Override public long getLength() { return delegate.getLength(); } } /** * */ public class DubbingByteBufferIterator implements Iterator { /** */ private HttpServletRequest request; /** */ private Iterator delegate; /** * */ public DubbingByteBufferIterator(HttpServletRequest request, Iterator delegate) { this.request = request; this.delegate = delegate; } /* (non-Javadoc) * @see java.util.Iterator#hasNext() */ @Override public boolean hasNext() { return delegate.hasNext(); } /* (non-Javadoc) * @see java.util.Iterator#next() */ @Override public ByteBuffer next() { ByteBuffer next = delegate.next(); exchangeListenerManager.onRequestContent(request, next.duplicate()); return next; } /* (non-Javadoc) * @see java.util.Iterator#remove() */ @Override public void remove() { delegate.remove(); } } }