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: [email protected]
Reporter: [email protected]
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: [email protected]
For additional commands, e-mail: [email protected]