Flushing The Document Early

This post is a note to myself and regards the Transfer-Encoding header field, defined in the HTTP spec. I was reminded of its use while reading Even Faster Web Sites.

First, some assumptions for the example that follows. Let’s say that the header of your page contains some annoying Flash banner advert that is downloaded from a different host and that the body of the page takes a few seconds to generate – in the example below I suspend the current thread for 10 seconds.

The page will be generated on the server and then served back to the browser. The browser will then parse the HTML and proceed to fetch the banner ad etc. In the meantime the user will be sitting there wondering what, if anything, is going on! So how can we present a more user-friendly page? Something that feels more responsive to the user. Enter the Transfer-Encoding header. By setting it to chunked we can serve the header part of the page – the first chunk – to the browser while the server works on generating the body of the page; in other words we don’t need to generate the page all in one go and then serve it up. The Transfer-Encoding header informs the browser that the content for the current page is going to come down the pipe in pieces (“chunks”) and not all at once. It also has the added benefit that as soon as the browser retrieves the first part of the page (the “header”) it can start to download the banner ad in parallel* while it waits for the remaining part of the page from the server. Overall the page should feel more responsive.

So, how to do it in a Java servlet. You would think you would just call the setHeader method on the servlet response object but you don’t – what were you thinking? Turns out it’s even easier than that! An example is given below:


void doGet(HttpServletRequest request,
           HttpServletResponse response)
   throws ServletException, IOException {

	response.setContentType("text/plain");
	PrintWriter out = response.getWriter();
	out.println("The start of the page.");
	out.flush();
	// Wait 10 seconds for no reason whatsoever
	try {
	     Thread.currentThread().sleep(10000);
	} catch (InterruptedException e) {
	     // Do nothing
	}
	out.println("The rest of the page ...");
}

Basically, if you write something to the output buffer and then call flush() that will automatically set the Transfer-Encoding header for you. If you remove the call to flush() then all the output will be buffered before it is sent back to the browser. If you fire up the example code in Tomcat (or something) and then look at it in a browser, the first line will be returned immediately followed 10 seconds later by the rest of the page; if you remove the call to flush() then the page content will be returned all at the same time after about 10 seconds or so.

End of note.

(*) Most browsers open up a limited number of connections to a given host. For example, Firefox 3 opens up a maximum of 6 connections at any one time to a given host.

Leave a Reply