Google Chrome’s blank/white page bug

A number of people have reported Google Chrome failing to load certain pages or websites, and instead showing a blank/white page. In many cases the problem is caused by the server returning a Content-Length header whose value is greater than the actual length of the content. While the sites concerned are at fault, it also seems fair to call Google Chrome’s behaviour a bug, as Firefox, Internet Explorer, Safari, and Opera are all able to render the pages correctly despite the incorrect Content-Length header. This page describes a specific cause of incorrect Content-Length headers, and explains how to fix the problem.

Content compression and ob_gzhandler

Most web browsers support content compression, a process whereby the web server compresses the data before sending it and the web browser decompresses the data upon receiving it. Content compression leads to websites loading faster and reduces the load on a server’s network connection.

PHP provides the ob_gzhandler function to ease the implementation of content compression. The ob_gzhandler function determines what form of compression (if any) the browser supports and compresses the content appropriately. The following example shows the basic structure of code using ob_gzhandler:

1
2
3
4
5
6
7
// enable compression
ob_start('ob_gzhandler');

// generate the content

// output the content
ob_end_flush();

Problems occur when the code tries to output the Content-Length header, as in the following flawed example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// enable compression
ob_start('ob_gzhandler');

// generate the content

// output the Content-Length header
header('Content-Length: ' . ob_get_length());

// output the content
ob_end_flush();

Sending the correct Content-Length header

The previous example fails because it outputs the length of the uncompressed content, which is greater than the length of the compressed content. To send the correct Content-Length header, the length of the compressed content must be measured, as shown in the following code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// enable compression
ob_start();
ob_start('ob_gzhandler');

// generate the content

// output the Content-Length header
ob_end_flush();
header('Content-Length: ' . ob_get_length());

// output the content
ob_end_flush();

This code uses two output buffers, with the ‘outer’ buffer received the compressed content from the ‘inner’ buffer. The call to ob_get_length on line 9 measures the size of the outer buffer, and as a result the Content-Length header correctly returns the length of the compressed content.

Where now?

Found this useful? Share it:

Also in PHP: