This helps avoid Zlib::DataError when a client disconnects on
the server while the server is writing the response.
This fixes the following backtraces on my server:
data error (Zlib::DataError)
rack/deflater.rb:124:in `close'
rack/deflater.rb:124:in `ensure in each'
rack/deflater.rb:124:in `each'
rack/chunked.rb:23:in `each'
...
---
If you prefer: git pull git://
80x24.org/rack zlib-disco
The following changes since commit c28f271d0c91f45e13bfa8f07bed445ef91f41de:
Merge pull request #942 from keepcosmos/remove-fulltest-guide (2015-09-08 07:45:02 -0700)
are available in the git repository at:
git://
80x24.org/rack zlib-disco
for you to fetch changes up to f769efe714f5b8b417e0440ce05f8b4e4b504c57:
deflater: always finish zlib stream before closing (2015-09-21 21:11:50 +0000)
----------------------------------------------------------------
Eric Wong (1):
deflater: always finish zlib stream before closing
lib/rack/deflater.rb | 3 ++-
test/spec_deflater.rb | 25 +++++++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/lib/rack/deflater.rb b/lib/rack/deflater.rb
index 19dc755..62a1124 100644
--- a/lib/rack/deflater.rb
+++ b/lib/rack/deflater.rb
@@ -118,8 +118,9 @@ module Rack
def each
deflator = ::Zlib::Deflate.new(*DEFLATE_ARGS)
@body.each { |part| yield deflator.deflate(part, Zlib::SYNC_FLUSH) }
- yield deflator.finish
+ yield fin = deflator.finish
ensure
+ deflator.finish unless fin
deflator.close
end
diff --git a/test/spec_deflater.rb b/test/spec_deflater.rb
index 2c7a428..ba7ec5d 100644
--- a/test/spec_deflater.rb
+++ b/test/spec_deflater.rb
@@ -114,6 +114,31 @@ describe Rack::Deflater do
end
end
+ it 'does not raise when a client aborts reading' do
+ app_body = Object.new
+ class << app_body; def each; yield('foo'); yield('bar'); end; end
+ opts = { 'skip_body_verify' => true }
+ verify(200, app_body, 'deflate', opts) do |status, headers, body|
+ headers.must_equal({
+ 'Content-Encoding' => 'deflate',
+ 'Vary' => 'Accept-Encoding',
+ 'Content-Type' => 'text/plain'
+ })
+
+ buf = []
+ inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
+ FakeDisconnect = Class.new(RuntimeError)
+ assert_raises(FakeDisconnect, "not Zlib::DataError not raised") do
+ body.each do |part|
+ buf << inflater.inflate(part)
+ raise FakeDisconnect
+ end
+ end
+ assert_raises(Zlib::BufError) { inflater.finish }
+ buf.must_equal(%w(foo))
+ end
+ end
+
# TODO: This is really just a special case of the above...
it 'be able to deflate String bodies' do
verify(200, 'Hello world!', 'deflate') do |status, headers, body|
--
EW