mod_deflate with mod_fastcgi gives wrong content-length header
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
libapache-mod-fastcgi (Debian) |
Fix Released
|
Unknown
|
|||
libapache-mod-fastcgi (Ubuntu) |
Triaged
|
Medium
|
Unassigned |
Bug Description
Binary package hint: libapache-
When compressing the content generated by mod_fastcgi, mod_deflate will keep any Content-Length header created by the script, instead of adjusting the header to match the compressed length.
References:
http://
http://
It seems that in surprisingly many cases this problem will go unnoticed by end users. Using Trac via FastCGI, however, I have encountered this issue repeatedly, and could even capture one instance using wireshark.
What I did was this:
1. Log into Trac account
2. Re-visit /trac/login
3. Get surprised by a Firefox dialog asking me to save the binary file "trac".
The traffic on the wire, starting at point 2 and reduced to the relevant parts:
> GET /trac/login/ HTTP/1.1
> Keep-Alive: 300
> Connection: keep-alive
< HTTP/1.1 302 Found
< Content-Length: 0
< Location: http://
< Content-Encoding: gzip
< Keep-Alive: timeout=15, max=100
< Connection: Keep-Alive
<
< [gzipped data, 0 bytes uncompressed, 26 bytes compressed]
> GET /trac HTTP/1.1
> Keep-Alive: 300
> Connection: keep-alive
< HTTP/1.1 301 Moved Permanently
< Content-Encoding: gzip
< Content-Length: 239
< Keep-Alive: timeout=15, max=99
< Connection: Keep-Alive
<
< [gzipped data, 297 bytes uncompressed, 239 bytes compressed]
What happens is this: firefox receives the first response, reads 0 bytes of content, and either because it didn't find any gzip header in those 0 bytes, or because it gives Content-Length preference over Content-Encoding in at least this case of a broken HTTP response, it decides that's it. The first 16 bytes of the gzipped empty content which were part of the same TCP frame as the headers seem to be discarded. However, the remaining 10 bytes are still on the wire, in their own TCP frame.
Next, FF sends a request for the next location. In this case, it matches a Redirect directive in my Apache configuration, so the next reply is generated by Apache itself, not through mod_fastcgi. The response is all right, but unfortunately, when reading it, FF first receives those 10 bytes left over from the last request. Seeing binary data instead of headers, it decides this must be a bad server sending binary content without headers, and offers to save this assumed binary file. When loking at the file, it's those 10 bytes, followed by the headers and compressed content for the next reply.
I had a look at some non-empty responses generated by trac/fast_
http://
The Debian bug does indicate libapache2_
Changed in libapache-mod-fastcgi (Debian): | |
status: | Unknown → New |
Changed in libapache-mod-fastcgi (Debian): | |
status: | New → Fix Released |
http:// thread. gmane.org/ gmane.comp. web.fastcgi. devel/2613 indicates another approach towards a solution, and it seems that a variation of it has been committed to some mod_fastcgi repository (though not the git at http:// repo.or. cz/w/mod_ fastcgi. git). It's also available in a snapshot dated 0811090952, but hasn't been officially released yet. The chunk in question is this one:
}
+
+ if (strcasecmp(name, "Content-Length") == 0) {
+ ap_table_
+ continue;
+ }
/* If the script wants them merged, it can do it */
ap_ table_add( r->err_ headers_ out, name, value);