Thursday, 28 April 2011

Chrome image bug and file headers

There is a bug in Chrome which means that, under some circumstances, an image can be displayed on the page for a moment and then disappear.

The fix is to remove the Content-Length header. Unfortunately that is virtually impossible to do in Drupal without hacking core.

Going into this problem revealed an interesting omission: the file_download() function collects headers from interested modules, but if two modules offer the same header the earlier one gets overwritten. Heavier modules can overwrite the headers of lighter modules.

So making my module heavy would mean that I could overwrite Content-Length with NULL.

But this is not a good solution. What's missing is that, after collecting the headers, file_download() does not use drupal_alter() to allow modules to change the headers.

So the correct solution is a patch which inserts drupal_alter('file_download_headers', $headers, $uri) into the file_download() function at the correct location. And you can find the patch here:

All I had to do then was create a function that implemented hook_file_download_headers() which took a look at the $uri and, if it's a graphic, remove the Content-Length header, which is perfectly safe because it's not a critical header.


jason said...

Thanks for the clear explanation of this issue. When I implement this fix (not your approach exactly) images now load properly in Chrome but it then breaks the loading of the same images in IE 9 (with and without compatibility mode). I guess IE wants Content-Length set properly. Any suggestions to address this?

Adaddinsane said...
This comment has been removed by the author.
Adaddinsane said...

Browser sniffing is the only solution - but since the image fetch will occur after the page fetch that's not a completely outrageous suggestion.

Anonymous said...

Thanks for the post -- this is exactly what is happening on my Drupal 6 site with Chrome.

I enabled the patch, but am not fully comfortable in Drupal programming. Are you able to help me (and others) with the hook_file_download_headers() function which can take a look at the $uri and, if it's a graphic, remove the Content-Length header? Thank you!

Adaddinsane said...

Sorry, I have to say no to that request - I know it seems mean but there are only so many hours in the day, and I never seem to have enough.

If you explore the parameters of the hook (using drupal_set_message(print_r(func_get_args(), TRUE)) should do the trick) you should be able to figure it out.