My example servlet prints out some data, flushes the buffer, sleeps for 5 seconds, then prints out more data and finishes.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("Before sleep<br/>");
writer.print("After newline<br/>");
writer.flush();
response.flushBuffer();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
writer.print("After sleep<br/>");
}
I expect the response body leading up to the flush
Before sleep<br/>
After newline<br/>
to be printed immediately, and 5 seconds later, the last piece.
Before sleep<br/>
After newline<br/>After sleep<br/>
When I query this servlet with curl -v
, the only immediate output is the headers and the response body leading up to (and including) the newline
Before sleep<br />
with the rest printed after 5 seconds.
Before sleep<br/>
After newline<br/>After sleep<br/>
It looks like the web container is line-buffering the response data. But that means the servlet can only flush response data before a newline, which seems to violate the specification.
Does anyone know why this is happening?
(I am using WildFly 8.2 with Java EE 7 / Servlets 3.1.)
After @JonSkeet suggested I look at the actual traffic, I've determined the line-buffering came from curl
. The raw HTTP response from the servlet returned this immediately
HTTP/1.1 200 OK
Content-Type: text/html;charset=ISO-8859-1
Transfer-Encoding: chunked
26
Before sleep<br />
After newline<br />
and after 5 seconds finished it off with
11
After sleep<br />
0
So maybe curl
was waiting to show the After newline<br />
bit as it was reconstructing the response body from the chunked transfer encoding.
Anyways, problem solved. Thank you!
Note to self: Use this curl
syntax which does not decode chunks
curl -i --raw
Now I get the output exactly as described above.