Description:
Undertow don't call onAllDataRead of ReadListener if inputStream.read is called more times
Priority of this jira is blocker, because this is regression against EAP 7.0.0 and EAP 7.1.0.ER1
Undertow works correctly, if I use 7.1.0.ER2 with Undertow from EAP 7.1.0.ER1
Example of REST end-point with ServletInputStream and custom ReadListener:
@Path("") public class ResourceInfoInjectionResource { protected static final Logger logger = Logger.getLogger(ResourceInfoInjectionResource.class.getName()); @Context private HttpServletRequest request; @POST @Path("async") public void async(@Suspended final AsyncResponse async) throws IOException { logger.info("Start async"); final ServletInputStream inputStream = request.getInputStream(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); inputStream.setReadListener(new ReadListener() { @Override public void onDataAvailable() throws IOException { logger.info("Start onDataAvailable"); // copy input stream byte[] buffer = new byte[4096]; int n1; while (-1 != (n1 = inputStream.read(buffer))) { outputStream.write(buffer, 0, n1); } logger.info("End onDataAvailable"); } @Override public void onAllDataRead() throws IOException { logger.info("Start onAllDataRead"); inputStream.close(); outputStream.flush(); outputStream.close(); async.resume(outputStream.toString(StandardCharsets.UTF_8.name())); logger.info("End onAllDataRead"); } @Override public void onError(Throwable t) { logger.info("Start onError"); async.resume(t); logger.info("End onError"); } }); logger.info("End async"); } }
Steps to Reproduce:
- ./standalone.sh
- prepare deployment
- download [^JBEAP-12223.zip]
- mvn clean package
- $JBOSS_HOME/bin/jboss-cli.sh -c
- deploy target/jaxrs-wf.war -f
- curl -v --data "aaa" -X POST -H "Content-Type: text/plain" http://127.0.0.1:8080/jaxrs-wf/async
Workaround
Use inputStream.isReady() check. In onDataAvailable method, use this:
while (inputStream.isReady()) {
n1 = inputStream.read(buffer);
outputStream.write(buffer, 0, n1);
}
instead of this:
while (-1 != (n1 = inputStream.read(buffer))) {
outputStream.write(buffer, 0, n1);
}
Additional info:
This can be reproduced also by pure servlet, for example this, if you remove isReady() check.
- clones
-
JBEAP-12223 If ServletInputStream.isReady returns false it is illegal to call the ServletInputStream.read method and an IllegalStateException MUST be thrown.
- Closed