Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit e44d908849c226f3d86930423f51228a4e1c7395 1 parent c868880
Dan Kubb authored
Showing with 19 additions and 1 deletion.
  1. +2 −1  lib/rack/deflater.rb
  2. +17 −0 test/spec_rack_deflater.rb
View
3  lib/rack/deflater.rb
@@ -1,5 +1,6 @@
require "zlib"
require "stringio"
+require "time" # for Time.httpdate
module Rack
@@ -28,7 +29,7 @@ def call(env)
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)]
View
17 test/spec_rack_deflater.rb
@@ -3,6 +3,7 @@
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 @@ class << body; def each; yield("foo"); yield("bar"); end; end
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
Please sign in to comment.
Something went wrong with that request. Please try again.