Some more details - here are the relevant places in the code that needed looking at, and my analysis:
Create incoming request:
{looks good, now strips out Transfer-Encoding header}
com.predic8.membrane.servlet.embedded.HttpServletHandler.createRequest()
--> com.predic8.membrane.core.http.Request.create(String, String, String, Header, InputStream)
------> com.predic8.membrane.core.http.Request.createBody(InputStream)
----------> com.predic8.membrane.core.http.Message.createBody(InputStream)
Create incoming response:
{looks good, uses chunked / unchunked as indicated by header}
com.predic8.membrane.core.transport.http.HttpClient.doCall(Exchange, Connection)
--> com.predic8.membrane.core.http.Response.read(InputStream, boolean)
------> com.predic8.membrane.core.http.Response.createBody(InputStream)
----------> com.predic8.membrane.core.http.Message.createBody(InputStream)
Create outgoing request:
{bad - writes unchunked in all cases, and without content-length. Need to add handling}
com.predic8.membrane.core.transport.http.HttpClient.doCall(Exchange, Connection)
--> com.predic8.membrane.core.http.Message.write(OutputStream)
------> com.predic8.membrane.core.http.AbstractBody.write(AbstractBodyTransferrer)
----------> com.predic8.membrane.core.http.AbstractBody.writeAlreadyRead(AbstractBodyTransferrer)
----------> com.predic8.membrane.core.http.AbstractBody.writeNotRead(AbstractBodyTransferrer)
(see ChunkedBody, PlainTextBody, etc...)
Create outgoing response:
{looks good, using PlainBodyTransferrer - missing ContentLength in some cases??}
com.predic8.membrane.servlet.embedded.HttpServletHandler.writeResponse(Response)
--> com.predic8.membrane.core.http.AbstractBody.write(AbstractBodyTransferrer)
------> com.predic8.membrane.core.http.AbstractBody.writeAlreadyRead(AbstractBodyTransferrer)
------> com.predic8.membrane.core.http.AbstractBody.writeNotRead(AbstractBodyTransferrer)
----------> using com.predic8.membrane.core.http.PlainBodyTransferrer
And here's how I finally changed the com.predic8.membrane.core.http.Message.write(OutputStream) method to fix the problem:
public final void write(OutputStream out) throws IOException {
// add chunked encoding here if it is missing. This is to make ALL outgoing messages chunked
// because messages written via this method go out the HttpClient, and are not subject to tomcat "auto-chunking"
// we make all messages chunked because the chunked/content-length headers get stripped out during processing.
boolean added = false;
if (header.getNumberOf(Header.TRANSFER_ENCODING)<1){
header.add(Header.TRANSFER_ENCODING, Header.CHUNKED);
added = true;
}
writeStartLine(out);
header.write(out);
out.write(Constants.CRLF_BYTES);
if (header.is100ContinueExpected()) {
out.flush();
return;
}
// when running in WAR / embedded mode in tomcat, the body never arrives chunked
// we prevent this block from running by stripping out the "transfer-encoding: chunked" header...
body.write(getHeader().isChunked() ? new ChunkedBodyTransferrer(out) : new PlainBodyTransferrer(out));
if (added)
header.removeFields(Header.TRANSFER_ENCODING);
out.flush();
}