This is an automated email from the ASF dual-hosted git repository.
remm 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 858118b592 Add testcase for BZ69545
858118b592 is described below
commit 858118b5928d943a706add1cbdf23b4bb7dc02b6
Author: remm <[email protected]>
AuthorDate: Tue Jan 28 21:05:16 2025 +0100
Add testcase for BZ69545
Still investigating.
---
.../http11/filters/TestChunkedInputFilter.java | 120 ++++++++++++++++++++-
1 file changed, 116 insertions(+), 4 deletions(-)
diff --git a/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
b/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
index c1866d9634..225a84fee7 100644
--- a/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
+++ b/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java
@@ -24,7 +24,10 @@ import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
+import jakarta.servlet.AsyncContext;
+import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -33,6 +36,7 @@ import org.junit.Assert;
import org.junit.Test;
import org.apache.catalina.Context;
+import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.SimpleHttpClient;
import org.apache.catalina.startup.TesterServlet;
import org.apache.catalina.startup.Tomcat;
@@ -816,6 +820,63 @@ public class TestChunkedInputFilter extends TomcatBaseTest
{
}
+ private static class NonBlockingReadLineServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ int lineCount = 0;
+ int pauseCount = 0;
+ long lastRead = 0;
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ final AsyncContext ctx = req.startAsync();
+ ServletInputStream is = req.getInputStream();
+ is.setReadListener(new ReadListener() {
+ @Override
+ public void onDataAvailable() throws IOException {
+ byte[] buf = new byte[1024];
+ do {
+ int n = is.read(buf);
+ if (n <= 0) {
+ break;
+ }
+ String line = new String(buf, 0, n,
StandardCharsets.UTF_8);
+ Assert.assertTrue(line.length() > 0);
+ long thisRead = System.nanoTime();
+ if (lineCount > 0) {
+ /*
+ * After the first line, look for a pause of at
least 800ms between reads.
+ */
+ if ((thisRead - lastRead) >
TimeUnit.MILLISECONDS.toNanos(800)) {
+ pauseCount++;
+ }
+ }
+ lastRead = thisRead;
+ lineCount++;
+ } while (is.isReady());
+ }
+
+ @Override
+ public void onAllDataRead() throws IOException {
+ resp.setContentType("text/plain");
+ PrintWriter pw = resp.getWriter();
+ pw.write(Integer.toString(lineCount) + "," +
Integer.toString(pauseCount));
+ ctx.complete();
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ throwable.printStackTrace();
+ }
+
+ });
+
+ }
+ }
+
+
private static class ReadLineClient extends SimpleHttpClient {
ReadLineClient(int port) {
@@ -852,17 +913,68 @@ public class TestChunkedInputFilter extends
TomcatBaseTest {
"Connection: close" + SimpleHttpClient.CRLF +
SimpleHttpClient.CRLF +
"7" + SimpleHttpClient.CRLF +
- "DATA01\n" + SimpleHttpClient.CRLF,
- "7" + SimpleHttpClient.CRLF +
+ "DATA01\n", SimpleHttpClient.CRLF +
+ "7", SimpleHttpClient.CRLF +
"DATA02\n" + SimpleHttpClient.CRLF,
"7" + SimpleHttpClient.CRLF +
// Split the CRLF between writes
"DATA03\n" + SimpleHttpClient.CR,
SimpleHttpClient.LF +
"7" + SimpleHttpClient.CRLF +
- "DATA04\n" + SimpleHttpClient.CRLF,
+ "DATA04\n", SimpleHttpClient.CRLF +
+ "13" + SimpleHttpClient.CRLF,
+ "DATA05DATA05DATA05\n" + SimpleHttpClient.CRLF +
+ "0" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF};
+
+ ReadLineClient client = new
ReadLineClient(tomcat.getConnector().getLocalPort());
+ client.setRequest(request);
+
+ client.connect(300000,300000);
+ client.processRequest();
+ Assert.assertTrue(client.isResponse200());
+ /*
+ * Output is "<lines read>,<pauses observer>" so there should be 5
lines read with a pause between each.
+ */
+ Assert.assertEquals("5,4", client.getResponseBody());
+ }
+
+
+ @Test
+ public void testChunkedSplitWithNonBlocking() throws Exception {
+ // Setup Tomcat instance
+ Tomcat tomcat = getTomcatInstance();
+
+ // No file system docBase required
+ Context ctx = getProgrammaticRootContext();
+
+ NonBlockingReadLineServlet servlet = new NonBlockingReadLineServlet();
+ Wrapper wrapper = Tomcat.addServlet(ctx, "servlet", servlet);
+ wrapper.setAsyncSupported(true);
+ ctx.addServletMappingDecoded("/test", "servlet");
+
+ tomcat.getConnector().setProperty("connectionTimeout", "300000");
+ tomcat.start();
+
+ String[] request = new String[]{
+ "POST /test HTTP/1.1" + SimpleHttpClient.CRLF +
+ "Host: any" + SimpleHttpClient.CRLF +
+ "Transfer-encoding: chunked" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.HTTP_HEADER_CONTENT_TYPE_FORM_URL_ENCODING +
+ "Connection: close" + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF +
+ "7" + SimpleHttpClient.CRLF +
+ "DATA01\n", SimpleHttpClient.CRLF +
+ "7"/*, */ + SimpleHttpClient.CRLF +
+ "DATA02\n" + SimpleHttpClient.CRLF,
+ "7" + SimpleHttpClient.CRLF +
+ // Split the CRLF between writes
+ "DATA03\n" + SimpleHttpClient.CR,
+ SimpleHttpClient.LF +
"7" + SimpleHttpClient.CRLF +
- "DATA05\n" + SimpleHttpClient.CRLF +
+ "DATA04\n", SimpleHttpClient.CRLF +
+ "13" + SimpleHttpClient.CRLF/*, */ +
+ "DATA05DATA05DATA05\n" + SimpleHttpClient.CRLF +
"0" + SimpleHttpClient.CRLF +
SimpleHttpClient.CRLF};
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]