You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2008/03/11 20:13:03 UTC

svn commit: r636066 - in /httpcomponents/httpcore/trunk/module-nio/src: main/java/org/apache/http/nio/entity/NHttpEntityWrapper.java test/java/org/apache/http/nio/protocol/TestNIOSSLHttp.java

Author: olegk
Date: Tue Mar 11 12:12:55 2008
New Revision: 636066

URL: http://svn.apache.org/viewvc?rev=636066&view=rev
Log:
Fixed bug in NHttpEntityWrapper causing infinite loop in the async protocol handlers 

Modified:
    httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/entity/NHttpEntityWrapper.java
    httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOSSLHttp.java

Modified: httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/entity/NHttpEntityWrapper.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/entity/NHttpEntityWrapper.java?rev=636066&r1=636065&r2=636066&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/entity/NHttpEntityWrapper.java (original)
+++ httpcomponents/httpcore/trunk/module-nio/src/main/java/org/apache/http/nio/entity/NHttpEntityWrapper.java Tue Mar 11 12:12:55 2008
@@ -77,8 +77,9 @@
         int i = this.channel.read(this.buffer);
         this.buffer.flip();
         encoder.write(this.buffer);
+        boolean buffering = this.buffer.hasRemaining(); 
         this.buffer.compact();
-        if (i == -1 && !this.buffer.hasRemaining()) {
+        if (i == -1 && !buffering) {
             encoder.complete();
             this.channel.close();
         }

Modified: httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOSSLHttp.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOSSLHttp.java?rev=636066&r1=636065&r2=636066&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOSSLHttp.java (original)
+++ httpcomponents/httpcore/trunk/module-nio/src/test/java/org/apache/http/nio/protocol/TestNIOSSLHttp.java Tue Mar 11 12:12:55 2008
@@ -47,6 +47,8 @@
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpVersion;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.StringEntity;
 import org.apache.http.message.BasicHttpEntityEnclosingRequest;
 import org.apache.http.message.BasicHttpRequest;
 import org.apache.http.mockup.ByteSequence;
@@ -56,6 +58,7 @@
 import org.apache.http.nio.NHttpConnection;
 import org.apache.http.nio.NHttpServiceHandler;
 import org.apache.http.nio.entity.NByteArrayEntity;
+import org.apache.http.nio.entity.NHttpEntityWrapper;
 import org.apache.http.nio.entity.NStringEntity;
 import org.apache.http.nio.protocol.HttpRequestExecutionHandler;
 import org.apache.http.nio.reactor.ListenerEndpoint;
@@ -649,4 +652,146 @@
         
     }
     
+    /**
+     * This test case executes a series of simple (non-pipelined) POST requests 
+     * with chunk coded content over multiple connections using 
+     * {@link NHttpEntityWrapper}. 
+     */
+    public void testSimpleBasicHttpEntityEnclosingRequestsChunkedWithWrapper() throws Exception {
+        
+        final int connNo = 1;
+        final int reqNo = 2;
+        final RequestCount requestCount = new RequestCount(connNo * reqNo); 
+        
+        final ByteSequence requestData = new ByteSequence();
+        requestData.rnd(reqNo);
+        
+        List<ByteSequence> responseData = new ArrayList<ByteSequence>(connNo);
+        for (int i = 0; i < connNo; i++) {
+            responseData.add(new ByteSequence());
+        }
+        
+        HttpRequestHandler requestHandler = new HttpRequestHandler() {
+
+            public void handle(
+                    final HttpRequest request, 
+                    final HttpResponse response, 
+                    final HttpContext context) throws HttpException, IOException {
+                
+                if (request instanceof HttpEntityEnclosingRequest) {
+                    HttpEntity incoming = ((HttpEntityEnclosingRequest) request).getEntity();
+                    byte[] data = EntityUtils.toByteArray(incoming);
+                    ByteArrayEntity outgoing = new ByteArrayEntity(data);
+                    outgoing.setChunked(true);
+                    response.setEntity(new NHttpEntityWrapper(outgoing));
+                } else {
+                    StringEntity outgoing = new StringEntity("No content"); 
+                    response.setEntity(new NHttpEntityWrapper(outgoing));
+                }
+            }
+            
+        };
+        
+        HttpRequestExecutionHandler requestExecutionHandler = new HttpRequestExecutionHandler() {
+
+            public void initalizeContext(final HttpContext context, final Object attachment) {
+                context.setAttribute("LIST", (ByteSequence) attachment);
+                context.setAttribute("REQ-COUNT", new Integer(0));
+                context.setAttribute("RES-COUNT", new Integer(0));
+            }
+
+            public void finalizeContext(final HttpContext context) {
+            }
+
+            public HttpRequest submitRequest(final HttpContext context) {
+                int i = ((Integer) context.getAttribute("REQ-COUNT")).intValue();
+                BasicHttpEntityEnclosingRequest post = null;
+                if (i < reqNo) {
+                    post = new BasicHttpEntityEnclosingRequest("POST", "/?" + i);
+                    byte[] bytes = requestData.getBytes(i);
+                    ByteArrayEntity outgoing = new ByteArrayEntity(bytes);
+                    outgoing.setChunked(true);
+                    post.setEntity(outgoing);
+                    
+                    context.setAttribute("REQ-COUNT", new Integer(i + 1));
+                }
+                return post;
+            }
+            
+            public void handleResponse(final HttpResponse response, final HttpContext context) {
+                NHttpConnection conn = (NHttpConnection) context.getAttribute(
+                        ExecutionContext.HTTP_CONNECTION);
+                
+                ByteSequence list = (ByteSequence) context.getAttribute("LIST");
+                int i = ((Integer) context.getAttribute("RES-COUNT")).intValue();
+                i++;
+                context.setAttribute("RES-COUNT", new Integer(i));
+                
+                try {
+                    HttpEntity entity = response.getEntity();
+                    byte[] data = EntityUtils.toByteArray(entity);
+                    list.addBytes(data);
+                    requestCount.decrement();
+                } catch (IOException ex) {
+                    requestCount.abort();
+                }
+
+                if (i < reqNo) {
+                    conn.requestInput();
+                }
+            }
+            
+        };
+        
+        SimpleEventListener serverEventListener = new SimpleEventListener();
+        SimpleEventListener clientEventListener = new SimpleEventListener();
+        
+        NHttpServiceHandler serviceHandler = createHttpServiceHandler(
+                requestHandler, 
+                null,
+                serverEventListener);
+
+        NHttpClientHandler clientHandler = createHttpClientHandler(
+                requestExecutionHandler, 
+                clientEventListener);
+
+        this.server.setRequestCount(requestCount);
+        this.client.setRequestCount(requestCount);
+        
+        this.server.start(serviceHandler);
+        this.client.start(clientHandler);
+
+        ListenerEndpoint endpoint = this.server.getListenerEndpoint();
+        endpoint.waitFor();
+        InetSocketAddress serverAddress = (InetSocketAddress) endpoint.getAddress();
+        
+        for (int i = 0; i < responseData.size(); i++) {
+            this.client.openConnection(
+                    new InetSocketAddress("localhost", serverAddress.getPort()), 
+                    responseData.get(i));
+        }
+     
+        requestCount.await(10000);
+        assertEquals(0, requestCount.getValue());
+        
+        this.client.shutdown();
+        this.server.shutdown();
+
+        for (int c = 0; c < responseData.size(); c++) {
+            ByteSequence receivedPackets = responseData.get(c);
+            ByteSequence expectedPackets = requestData;
+            assertEquals(expectedPackets.size(), receivedPackets.size());
+            for (int p = 0; p < requestData.size(); p++) {
+                byte[] expected = requestData.getBytes(p);
+                byte[] received = receivedPackets.getBytes(p);
+                
+                assertEquals(expected.length, received.length);
+                for (int i = 0; i < expected.length; i++) {
+                    assertEquals(expected[i], received[i]);
+                }
+            }
+        }
+        
+    }
+
 }