Adam Butkiewicz created HTTPCORE-803:
----------------------------------------

             Summary: Chunked encoding: Last chunk is written on failure
                 Key: HTTPCORE-803
                 URL: https://issues.apache.org/jira/browse/HTTPCORE-803
             Project: HttpComponents HttpCore
          Issue Type: Bug
          Components: HttpCore
            Reporter: Adam Butkiewicz


In my proxy (Spring MVC with http components transport) I noticed a chunked 
encoding request streaming failed on reading from client. It was visible as 500 
in the proxy and as a valid request without a body (even though client did send 
the body) in the underlying server.

I believe the culprit is "finish()" called during "close()". I'm not sure if it 
is a bug but such behavior is odd. At first glance, I would expect nothing more 
to be written on "close()" so that underying server could detect the requets is 
invalid.

This is a patch with a test case which demonstrates what I mean: 
{code:java}
Index: 
httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git 
a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
 
b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
--- 
a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
    (revision 57428d2b8c8e9c087a88258359b7ea353a45d971)
+++ 
b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/io/TestDefaultBHttpClientConnection.java
    (date 1793960803181)
@@ -28,7 +28,10 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.Socket;
 import java.nio.charset.StandardCharsets;
 
@@ -41,6 +44,7 @@
 import org.apache.hc.core5.http.NotImplementedException;
 import org.apache.hc.core5.http.config.Http1Config;
 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
 import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
 import org.apache.hc.core5.http.io.entity.StringEntity;
 import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
@@ -297,6 +301,59 @@
                 "chunked\r\n\r\n3\r\n123\r\n0\r\n\r\n", s);
     }
 
+    @Test
+    void testWriteRequestEntityChunkCodedFailureDoesNotTerminateMessage() 
throws Exception {
+        final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        Mockito.when(socket.getOutputStream()).thenReturn(outStream);
+
+        conn.bind(socket);
+
+        final ClassicHttpRequest request = new 
BasicClassicHttpRequest(Method.POST, "/stuff");
+        request.addHeader("User-Agent", "test");
+        request.addHeader("Transfer-Encoding", "chunked");
+        request.setEntity(new AbstractHttpEntity(ContentType.TEXT_PLAIN, null, 
true) {
+
+            @Override
+            public void writeTo(final OutputStream out) throws IOException {
+                out.write("123".getBytes(StandardCharsets.US_ASCII));
+                throw new EOFException("source stream failed");
+            }
+
+            @Override
+            public InputStream getContent() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public long getContentLength() {
+                return -1;
+            }
+
+            @Override
+            public boolean isRepeatable() {
+                return false;
+            }
+
+            @Override
+            public boolean isStreaming() {
+                return true;
+            }
+
+            @Override
+            public void close() {
+            }
+
+        });
+
+        conn.sendRequestHeader(request);
+        Assertions.assertThrows(EOFException.class, () -> 
conn.sendRequestEntity(request));
+
+        final String s = new String(outStream.toByteArray(), 
StandardCharsets.US_ASCII);
+        final String body = s.substring(s.indexOf("\r\n\r\n") + 4);
+        Assertions.assertFalse(body.endsWith("0\r\n\r\n"),
+                "Incomplete entity must not be sent as a terminated 
chunk-coded message: " + body);
+    }
+
     @Test
     void testWriteRequestEntityNoContentLength() throws Exception {
         final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
{code}
 

 



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to