From 0ba88559cd15ffc2b7a0fed7a05d62622349ea6f Mon Sep 17 00:00:00 2001 From: Eugene Kenny Date: Fri, 29 Jul 2022 03:48:15 +0100 Subject: 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. --- lib/rack/deflater.rb | 2 +- test/spec_deflater.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) 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 -- cgit v1.2.3-24-ge0c7