summary refs log tree commit
diff options
context:
space:
mode:
authorDan Kubb <dan.kubb@autopilotmarketing.com>2008-12-20 13:36:22 -0800
committerDan Kubb <dan.kubb@autopilotmarketing.com>2008-12-20 13:36:22 -0800
commite44d908849c226f3d86930423f51228a4e1c7395 (patch)
tree2d0dc43cbc3d56128a624146295b4bb014949dac
parentc868880e376c79a61bc5884ee48061d7092d0a04 (diff)
downloadrack-e44d908849c226f3d86930423f51228a4e1c7395.tar.gz
Fixed Rack::Deflater to handle responses with Last-Modified header
* There was a bug when performing gzip compression where the
  Last-Modified response header was assumed to be a Time object,
  and passed directly to Zlib::GzipWriter#mtime, causing an exception
  since it is always a String.

  This fix parses the Last-Modified header using Time.httpdate and
  returns a Time obejct, which can be safely passed to
  Zlib::GzipWriter#mtime.
-rw-r--r--lib/rack/deflater.rb3
-rw-r--r--test/spec_rack_deflater.rb17
2 files changed, 19 insertions, 1 deletions
diff --git a/lib/rack/deflater.rb b/lib/rack/deflater.rb
index fa71bcac..e28dd082 100644
--- a/lib/rack/deflater.rb
+++ b/lib/rack/deflater.rb
@@ -1,5 +1,6 @@
 require "zlib"
 require "stringio"
+require "time"  # for Time.httpdate
 
 module Rack
 
@@ -28,7 +29,7 @@ class Deflater
 
     case encoding
     when "gzip"
-      mtime = headers["Last-Modified"] || Time.now
+      mtime = headers.key?("Last-Modified") ? Time.httpdate(headers["Last-Modified"]) : Time.now
       [status, headers.merge("Content-Encoding" => "gzip"), self.class.gzip(body, mtime)]
     when "deflate"
       [status, headers.merge("Content-Encoding" => "deflate"), self.class.deflate(body)]
diff --git a/test/spec_rack_deflater.rb b/test/spec_rack_deflater.rb
index f86d0a21..63546215 100644
--- a/test/spec_rack_deflater.rb
+++ b/test/spec_rack_deflater.rb
@@ -3,6 +3,7 @@ require 'test/spec'
 require 'rack/mock'
 require 'rack/deflater'
 require 'stringio'
+require 'time'  # for Time#httpdate
 
 context "Rack::Deflater" do
   def build_response(status, body, accept_encoding, headers = {})
@@ -75,4 +76,20 @@ context "Rack::Deflater" do
     response2[1].should.equal({"Content-Type" => "text/plain"})
     response2[2].should.equal("An acceptable encoding for the requested resource /foo/bar could not be found.")
   end
+
+  specify "should handle gzip response with Last-Modified header" do
+    last_modified = Time.now.httpdate
+
+    app = lambda { |env| [200, { "Last-Modified" => last_modified }, "Hello World!"] }
+    request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
+    response = Rack::Deflater.new(app).call(request)
+
+    response[0].should.equal(200)
+    response[1].should.equal({ "Content-Encoding" => "gzip", "Vary" => "Accept-Encoding", "Last-Modified" => last_modified })
+
+    io = StringIO.new(response[2].to_s)
+    gz = Zlib::GzipReader.new(io)
+    gz.read.should.equal("Hello World!")
+    gz.close
+  end
 end