candrews/HttpResponseCache

incorrect content-length causes problems on ssl connection

jaypatrickhoward opened this issue · 1 comments

I'm seeing an issue where, with the cache installed, loading images over an SSL connection occasionally results in garbage bytes being returned. This doesn't happen when they're loaded over plain HTTP. It also doesn't happen when the images are loaded over SSL without the HttpResponseCache installed.

I verified that the behavior is present even when I use the stock HttpResponseCache in Android 4.2.2. So it's not a problem with your port per se. Figured I'd post here, though, since I currently use your version in my app even when the stock version is present.

My current hunch is that it's misbehavior on Apache's part that's triggering this. My Apache installation seems to respond with an incorrect content length when the images are loaded over SSL. I say this because when I load them in Firefox and click "View Image Info" the non-SSL-loaded version always reports the right size whereas the SSL-loaded version reports an incorrect size. I'm guessing Firefox just uses the Content-Length value in that dialog instead of the actual number of bytes it read. It can decode and display the images in both cases, though, even when the Content-Length is wrong, so it's getting the correct bytes.

Here are two URLs that illustrate the bad Apache behavior. The only difference is HTTP vs. HTTPS:

http://rsdevelopment.malauzai.com/images/organizationdata/MMB/3.0.0/android-high-dpi/en_us/share_facebookbutton_img_20130502105154.png

https://rsdevelopment.malauzai.com/images/organizationdata/MMB/3.0.0/android-high-dpi/en_us/share_facebookbutton_img_20130502105154.png

Any thoughts on how I might start debugging this and whether it's likely to be fixable in the HttpResponseCache (or DiskLruCache) code?

Or, alternately, any idea what the hell is wrong with my Apache server? :)

I figured out what's going on with Apache.

Our server is configured to return compressed content (mod_deflate) when the request comes in over HTTPS but not otherwise. Apache chooses a transfer mode based on whether the content's length exceeds its "DeflateBufferSize" setting.

If the content is greater than DeflateBufferSize then the server uses chunked mode, which means no "Content-Length" is included with the response. HttpResponseCache handles this case correctly.

However, if the content is less than DeflateBufferSize then it sends a value for "Content-Length" that is the length of the compressed data. This is the case that HttpResponseCache doesn't handle correctly.

The problem disappears when I load the images over HTTP because our server is configured to only use compression for HTTPS. It has nothing to do with SSL whatsoever.

What I suspect is happening is that the somewhere in the cache code a comparison is made between "reported content-length" and "bytes read" in order to detect incomplete responses, but the "bytes read" value used is the byte count of the decoded content instead of the byte count of the raw content, which is what "Content-Length" is supposed to describe.