https://bz.apache.org/bugzilla/show_bug.cgi?id=62605
Bug ID: 62605 Summary: Async servlet over HTTP/2 setReadListener does not work if post request data arrives much later than headers Product: Tomcat 9 Version: 9.0.10 Hardware: PC OS: Linux Status: NEW Severity: normal Priority: P2 Component: Servlet Assignee: dev@tomcat.apache.org Reporter: zdap...@google.com Target Milestone: ----- [Previously I filed an invalid bug https://bz.apache.org/bugzilla/show_bug.cgi?id=62569 , which was not producible with telnet client over HTTP/1.1, sorry about that] The issue is reproducible when using client over HTTP/2 Steps to reproduce: 1. Enable HTTP/2 for Tomcat <Connector port="8080" protocol="HTTP/1.1"> <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/> </Connector> 2. Deploy the following Servlet (basically the same as the tutorial example https://javaee.github.io/tutorial/servlets013.html with more debug info and fixing reading EOS problem) @WebServlet(urlPatterns={"/asyncioservlet"}, asyncSupported=true) public class AsyncIOServlet extends HttpServlet { @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { final AsyncContext acontext = request.startAsync(); final ServletInputStream input = request.getInputStream(); System.out.println("Set listener"); input.setReadListener( new ReadListener() { byte buffer[] = new byte[4 * 1024]; StringBuilder sbuilder = new StringBuilder(); @Override public void onDataAvailable() { System.out.println("onDataAvailable"); try { do { int length = input.read(buffer); System.out.println("length = " + length); if (length == -1) { return; } sbuilder.append(new String(buffer, 0, length)); } while (input.isReady()); } catch (IOException ex) { ex.printStackTrace(); } catch (RuntimeException e) { e.printStackTrace(); } } @Override public void onAllDataRead() { System.out.println("onAllDataRead"); try { acontext.getResponse().getWriter().write("...the response..."); } catch (IOException ex) { ex.printStackTrace(); } acontext.complete(); } @Override public void onError(Throwable t) { t.printStackTrace(); } }); System.out.println("Set listener - done"); } 3. Make sure the curl command supports HTTP/2 $ curl --version curl 7.60.0 Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL 4. Run the following curl command $ (sleep 2s; echo "hello world") | curl --http2 --http2-prior-knowledge http://localhost:8080/asyncioservlet -H "content-type: text/plain" -T - -X POST (for TLS use the following command, I didn't check the TLS case though) $ (sleep 2s; echo "hello world") | curl --http2 --http2-prior-knowledge https://localhost:8443/asyncioservlet -H "content-type: text/plain" -T - -X POST -k 5. The client will hang, and check the server log "logs/catalina.out" Set listener Set listener - done no sign of ReadListener callbacks invoked. 6. Without the sleep, the client does not hang, and ReadListener callbacks get invoked. Deploying the same servlet to Glassfish/Undertow/Jetty will not see this problem. -- You are receiving this mail because: You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org