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 <r...@apache.org> 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: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org