Skip to content

Commit

Permalink
Close the original body passed to Rack::ETag
Browse files Browse the repository at this point in the history
The Rack spec states:

> If the Body responds to `close`, it will be called after iteration. If
> the body is replaced by a middleware after action, the original body
> must be closed first, if it responds to close.

After Rack::ETag replaces the response body, close the original body.

Signed-off-by: David Celis <me@davidcel.is>
  • Loading branch information
davidcelis committed Sep 29, 2013
1 parent 1f47a44 commit 3a388bc
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/rack/etag.rb
Expand Up @@ -62,6 +62,8 @@ def digest_body(body)
(digest ||= Digest::MD5.new) << part unless part.empty?
end

body.close if body.respond_to?(:close)

[digest && digest.hexdigest, parts]
end
end
Expand Down
18 changes: 16 additions & 2 deletions test/spec_etag.rb
Expand Up @@ -7,17 +7,24 @@
def etag(app, *args)
Rack::Lint.new Rack::ETag.new(app, *args)
end

def request
Rack::MockRequest.env_for
end

def sendfile_body
res = ['Hello World']
def res.to_path ; "/tmp/hello.txt" ; end
res
end

def closable_body
res = ['Hello World']
def res.close ; @closed = true ; end
def res.closed? ; !!@closed ; end
res
end

should "set ETag if none is set if status is 200" do
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
response = etag(app).call(request)
Expand Down Expand Up @@ -95,4 +102,11 @@ def res.to_path ; "/tmp/hello.txt" ; end
response = etag(app).call(request)
response[1]['ETag'].should.be.nil
end

should "close the original body if it responds to close" do
body = closable_body
app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
etag(app).call(request)
body.should.be.closed
end
end

0 comments on commit 3a388bc

Please sign in to comment.