This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new e62cf34b1c Ensure onAllDataRead() fires with chunked request body
e62cf34b1c is described below
commit e62cf34b1c1e4c56d1a448735337fe30a7eb96eb
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Apr 23 13:48:49 2024 +0100
Ensure onAllDataRead() fires with chunked request body
---
.../coyote/http11/filters/ChunkedInputFilter.java | 15 ++++++++
.../catalina/nonblocking/TestNonBlockingAPI.java | 45 ++++++++++++++++++++++
webapps/docs/changelog.xml | 5 +++
3 files changed, 65 insertions(+)
diff --git a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
index 13dcb7d53f..c0b74a185f 100644
--- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
@@ -24,6 +24,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import org.apache.coyote.ActionCode;
import org.apache.coyote.BadRequestException;
import org.apache.coyote.InputBuffer;
import org.apache.coyote.Request;
@@ -167,6 +168,20 @@ public class ChunkedInputFilter implements InputFilter,
ApplicationBufferHandler
}
if (endChunk) {
parseEndChunk();
+ if (!request.isRequestThread()) {
+ /*
+ * Perform the dispatch back to the container for the
onAllDataRead() event. For non-chunked input
+ * this would be performed when isReady() is next called.
+ *
+ * Chunked input returns one chunk at a time for
non-blocking reads. A consequence of this is that
+ * reading the final chunk returns -1 which signals the
end of stream. The application code reading
+ * the request body probably won't call isReady() after
receiving the -1 return value since it
+ * already knows it is at end of stream. Therefore we
trigger the dispatch back to the container
+ * here which in turn ensures the onAllDataRead() event is
fired.
+ */
+ request.action(ActionCode.DISPATCH_READ, null);
+ request.action(ActionCode.DISPATCH_EXECUTE, null);
+ }
return -1;
}
}
diff --git a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
index 6d2e202031..66fbf2ac12 100644
--- a/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
+++ b/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java
@@ -155,6 +155,51 @@ public class TestNonBlockingAPI extends TomcatBaseTest {
}
+ @Test
+ public void testNonBlockingReadChunked() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ // No file system docBase required
+ Context ctx = getProgrammaticRootContext();
+
+ NBReadServlet servlet = new NBReadServlet(false, true);
+ String servletName = NBReadServlet.class.getName();
+ Tomcat.addServlet(ctx, servletName, servlet);
+ ctx.addServletMappingDecoded("/", servletName);
+
+ tomcat.start();
+
+ Client client = new Client();
+ client.setPort(getPort());
+ client.setRequest(new String[] { "GET / HTTP/1.1" +
SimpleHttpClient.CRLF +
+ "Host: localhost:" + getPort() +
SimpleHttpClient.CRLF +
+ "Transfer-Encoding: chunked" +
SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF +
+ "14" + SimpleHttpClient.CRLF +
+ "01234567890123456789" +
SimpleHttpClient.CRLF +
+ "14" + SimpleHttpClient.CRLF +
+ "012345678901FINISHED" +
SimpleHttpClient.CRLF +
+ "0" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF});
+ client.connect();
+ client.sendRequest();
+
+ client.setUseContentLength(true);
+ client.readResponse(true);
+
+ Assert.assertTrue(client.isResponse200());
+ Assert.assertTrue(client.isResponseBodyOK());
+ }
+
+
+ private static class Client extends SimpleHttpClient {
+ @Override
+ public boolean isResponseBodyOK() {
+ return "OK".equals(getResponseBody());
+ }
+ }
+
+
@Test
public void testNonBlockingWrite() throws Exception {
testNonBlockingWriteInternal(false);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index c0cf843180..84ba411ffe 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -159,6 +159,11 @@
failed. The wait time is now 100ms plus twice
<code>socket.unlockTimeout</code>. (markt)
</fix>
+ <fix>
+ Ensure that the <code>onAllDataRead()</code> event is triggered when
the
+ request body uses chunked encoding and is read using non-blocking IO.
+ (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Other">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]