diff options
author | Eugene Kenny <elkenny@gmail.com> | 2022-07-29 03:48:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-29 14:48:15 +1200 |
commit | 0ba88559cd15ffc2b7a0fed7a05d62622349ea6f (patch) | |
tree | cf26f1fe73b5673711a23b791cee59a7dad7fe36 | |
parent | 63ca628d7809758b332021e2f1f9ee69f4252441 (diff) | |
download | rack-0ba88559cd15ffc2b7a0fed7a05d62622349ea6f.tar.gz |
Don't close body prematurely in Rack::Deflater (#1931)
GzipWriter#close also closes the underlying IO, which in turn closes the wrapped response body. If that body is a Rack::BodyProxy, the associated block will run too early, before control has returned to the app server. GzipWriter#finish closes the gzip stream, but not the underlying IO. The response body will then be closed by the app server after iteration.
-rw-r--r-- | lib/rack/deflater.rb | 2 | ||||
-rw-r--r-- | test/spec_deflater.rb | 9 |
2 files changed, 10 insertions, 1 deletions
diff --git a/lib/rack/deflater.rb b/lib/rack/deflater.rb index 3f6177e6..cc01c32a 100644 --- a/lib/rack/deflater.rb +++ b/lib/rack/deflater.rb @@ -116,7 +116,7 @@ module Rack } end ensure - gzip.close + gzip.finish end # Call the block passed to #each with the gzipped data. diff --git a/test/spec_deflater.rb b/test/spec_deflater.rb index 6cac22ac..23880eaa 100644 --- a/test/spec_deflater.rb +++ b/test/spec_deflater.rb @@ -510,4 +510,13 @@ describe Rack::Deflater do raw_bytes.must_be(:<, content.bytesize) end end + + it 'does not close the response body prematurely' do + app_body = Object.new + class << app_body; attr_reader :closed; def each; yield('foo'); yield('bar'); end; def close; @closed = true; end; end + + verify(200, 'foobar', deflate_or_gzip, { 'app_body' => app_body }) do |status, headers, body| + assert_nil app_body.closed + end + end end |