Ignore:
Timestamp:
02/21/14 19:27:26 (11 years ago)
Author:
pharms
Message:
  • correct 2 bugs: one an implementation bug in encoding queries in the Jetty HTML client and another one when proxying CXF SOAP exchanges where the server is deployed in a tomcat.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-httpmonitor/src/main/java/de/ugoe/cs/autoquest/httpmonitor/proxy/HttpMonitoringProxyServlet.java

    r1389 r1392  
    1616 
    1717import java.io.IOException; 
     18import java.io.UnsupportedEncodingException; 
    1819import java.net.URI; 
    1920import java.net.URISyntaxException; 
     21import java.net.URLEncoder; 
    2022import java.nio.ByteBuffer; 
     23import java.nio.charset.UnsupportedCharsetException; 
    2124import java.util.Iterator; 
     25import java.util.LinkedList; 
     26import java.util.List; 
    2227 
    2328import javax.servlet.http.HttpServletRequest; 
    2429import javax.servlet.http.HttpServletResponse; 
    2530 
     31import org.eclipse.jetty.client.HttpClient; 
     32import org.eclipse.jetty.client.HttpRequest; 
    2633import org.eclipse.jetty.client.api.ContentProvider; 
    2734import org.eclipse.jetty.client.api.Request; 
    2835import org.eclipse.jetty.client.api.Response; 
    2936import org.eclipse.jetty.proxy.ProxyServlet; 
     37import org.eclipse.jetty.util.Fields; 
    3038 
    3139import de.ugoe.cs.autoquest.httpmonitor.exchange.Status; 
     
    4149 * recorded exchange. 
    4250 * </p> 
     51 * <p> 
     52 * The implementation also overrides the default implementation of the jetty HTTP client 
     53 * and the jetty HTTP request to fix a bug in forwarding queries. 
     54 * </p> 
    4355 *  
    4456 * @author Patrick Harms 
     
    97109            return null; 
    98110        } 
     111    } 
     112 
     113    /* (non-Javadoc) 
     114     * @see org.eclipse.jetty.proxy.ProxyServlet#newHttpClient() 
     115     */ 
     116    @Override 
     117    protected HttpClient newHttpClient() { 
     118        return new BugfixedHttpClient(); 
    99119    } 
    100120 
     
    200220 
    201221    /** 
    202      * This iterator is used to implement the {@link DubbingContentProvider}. It works in the  
    203      * same manner and uses delegation for wrapping the original iterator and forwards all copied 
    204      * data to the exchange listener manager. 
     222     * This iterator is used to implement the {@link DubbingContentProvider}. It uses delegation 
     223     * for wrapping the original iterator and forwards all copied data to the exchange listener 
     224     * manager. Furthermore, it combines several buffers into one. This seems to be required if 
     225     * SOAP messages are proxied. 
    205226     */ 
    206227    public class DubbingByteBufferIterator implements Iterator<ByteBuffer> { 
     
    237258        @Override 
    238259        public ByteBuffer next() { 
    239             ByteBuffer next = delegate.next(); 
    240             exchangeListenerManager.onRequestContent(request, next.duplicate()); 
    241             return next; 
     260            List<ByteBuffer> buffers = new LinkedList<ByteBuffer>(); 
     261             
     262            int size = 0; 
     263            while (delegate.hasNext()) { 
     264                ByteBuffer next = delegate.next(); 
     265                exchangeListenerManager.onRequestContent(request, next.duplicate()); 
     266 
     267                ByteBuffer copy = ByteBuffer.allocate(next.limit()); 
     268                copy.put(next); 
     269                copy.position(0); 
     270                buffers.add(copy); 
     271                 
     272                size += next.limit(); 
     273            } 
     274             
     275            ByteBuffer buffer = ByteBuffer.allocate(size); 
     276             
     277            for (ByteBuffer orig : buffers) { 
     278                buffer.put(orig); 
     279            } 
     280             
     281            buffer.position(0); 
     282             
     283            return buffer; 
    242284        } 
    243285 
     
    247289        @Override 
    248290        public void remove() { 
    249             delegate.remove(); 
    250         } 
    251  
    252     } 
    253  
     291            while (delegate.hasNext()) { 
     292                delegate.remove(); 
     293            } 
     294        } 
     295 
     296    } 
     297 
     298    /** 
     299     * <p> 
     300     * bugfix implementation of the jetty HTTP client to be able to use only bugfixed HTTP requests 
     301     * </p> 
     302     *  
     303     * @author Patrick Harms 
     304     */ 
     305    private class BugfixedHttpClient extends HttpClient { 
     306 
     307        /* (non-Javadoc) 
     308         * @see org.eclipse.jetty.client.HttpClient#newRequest(java.net.URI) 
     309         */ 
     310        @Override 
     311        public Request newRequest(URI uri) { 
     312            return new BugfixedHttpRequest(this, uri); 
     313        } 
     314 
     315    } 
     316 
     317    /** 
     318     * <p> 
     319     * bugfix implementation of the jetty HTTP request. This ensures that query string 
     320     * representations are correctly forwarded in the case that a query parameter does not have 
     321     * a value.  
     322     * </p> 
     323     *  
     324     * @author Patrick Harms 
     325     */ 
     326    private class BugfixedHttpRequest extends HttpRequest { 
     327 
     328        /** 
     329         * <p> 
     330         * Constructor to override parent constructor 
     331         * </p>  
     332         */ 
     333        BugfixedHttpRequest(HttpClient client, URI uri) { 
     334            super(client, uri); 
     335        } 
     336 
     337        /* 
     338         * (non-Javadoc) 
     339         *  
     340         * @see org.eclipse.jetty.client.HttpRequest#getQuery() 
     341         */ 
     342        @Override 
     343        public String getQuery() { 
     344            return buildQuery(); 
     345        } 
     346 
     347        /** 
     348         * <p> 
     349         * this corrects the bug implemented in the parent class on creating the query string 
     350         * </p> 
     351         *  
     352         * @return the correct query string 
     353         */ 
     354        private String buildQuery() { 
     355            StringBuilder result = new StringBuilder(); 
     356            for (Iterator<Fields.Field> iterator = super.getParams().iterator(); iterator.hasNext();) 
     357            { 
     358                Fields.Field field = iterator.next(); 
     359                String[] values = field.values(); 
     360                for (int i = 0; i < values.length; ++i) { 
     361                    if (i > 0) { 
     362                        result.append("&"); 
     363                    } 
     364 
     365                    result.append(field.name()); 
     366 
     367                    if ((values[i] != null) && (!"".equals(values[i].trim()))) { 
     368                        result.append("="); 
     369                        result.append(urlEncode(values[i])); 
     370                    } 
     371                } 
     372                if (iterator.hasNext()) { 
     373                    result.append("&"); 
     374                } 
     375            } 
     376            return result.toString(); 
     377        } 
     378 
     379        /** 
     380         * <p> 
     381         * convenience method copied from parent class, as it is private there. 
     382         * </p> 
     383         *  
     384         * @see HttpRequest#urlEncode(String) 
     385         */ 
     386        private String urlEncode(String value) { 
     387            String encoding = "UTF-8"; 
     388            try { 
     389                return URLEncoder.encode(value, encoding); 
     390            } 
     391            catch (UnsupportedEncodingException e) { 
     392                throw new UnsupportedCharsetException(encoding); 
     393            } 
     394        } 
     395    } 
    254396} 
Note: See TracChangeset for help on using the changeset viewer.