From 6b55d11c08daafc8e4ec84fb04efc29c8adc7bd8 Mon Sep 17 00:00:00 2001 From: zedshaw Date: Tue, 24 Oct 2006 23:22:16 +0000 Subject: [PATCH] Patch #6275 for improved deflate filter support for IE and Safari. git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@366 19e92222-5c0b-0410-8929-a290d50e31e9 --- lib/mongrel/handlers.rb | 24 ++++++++++++++++++------ test/test_handlers.rb | 19 ++++++++++++++++--- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/lib/mongrel/handlers.rb b/lib/mongrel/handlers.rb index fb32d2e5..d19f3bba 100644 --- a/lib/mongrel/handlers.rb +++ b/lib/mongrel/handlers.rb @@ -282,6 +282,7 @@ module Mongrel # Valid option is :always_deflate => false which tells the handler to # deflate everything even if the client can't handle it. class DeflateFilter < HttpHandler + include Zlib HTTP_ACCEPT_ENCODING = "HTTP_ACCEPT_ENCODING" def initialize(ops={}) @@ -294,14 +295,25 @@ module Mongrel # only process if they support compression if @always_deflate or (accepts and (accepts.include? "deflate" and not response.body_sent)) response.header["Content-Encoding"] = "deflate" - # we can't just rewind the body and gzip it since the body could be an attached file - response.body.rewind - gzout = StringIO.new(Zlib::Deflate.deflate(response.body.read)) - gzout.rewind - response.body.close - response.body = gzout + response.body = deflate(response.body) end end + + private + def deflate(stream) + deflater = Deflate.new( + DEFAULT_COMPRESSION, + # drop the zlib header which causes both Safari and IE to choke + -MAX_WBITS, + DEF_MEM_LEVEL, + DEFAULT_STRATEGY) + + stream.rewind + gzout = StringIO.new(deflater.deflate(stream.read, FINISH)) + stream.close + gzout.rewind + gzout + end end diff --git a/test/test_handlers.rb b/test/test_handlers.rb index 7df0f15a..98f83c08 100644 --- a/test/test_handlers.rb +++ b/test/test_handlers.rb @@ -45,7 +45,7 @@ class HandlersTest < Test::Unit::TestCase uri "/", :handler => SimpleHandler.new uri "/", :handler => stats uri "/404", :handler => Mongrel::Error404Handler.new("Not found") - uri "/dumb", :handler => Mongrel::DeflateFilter.new(:always_deflate => true) + uri "/dumb", :handler => Mongrel::DeflateFilter.new uri "/dumb", :handler => DumbHandler.new, :in_front => true uri "/files", :handler => Mongrel::DirHandler.new("doc") uri "/files_nodir", :handler => Mongrel::DirHandler.new("doc",listing_allowed=false, index_html="none") @@ -73,8 +73,21 @@ class HandlersTest < Test::Unit::TestCase check_status res, String end - def test_deflate_access - req = Net::HTTP::Get.new("http://localhost:9998/dumb") + def test_deflate + Net::HTTP.start("localhost", 9998) do |h| + # test that no accept-encoding returns a non-deflated response + req = h.get("/dumb") + assert( + !req.header['Content-Encoding'] || + !req.header['Content-Encoding'].include?('deflate')) + assert_equal "test", req.body + + req = h.get("/dumb", {"Accept-Encoding" => "deflate"}) + # -MAX_WBITS stops zlib from looking for a zlib header + inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS) + assert req.header['Content-Encoding'].include?('deflate') + assert_equal "test", inflater.inflate(req.body) + end end # TODO: find out why this fails on win32 but nowhere else