Skip to content

Commit

Permalink
Mechanize now ignores a missing gzip footer like browsers do. sparkle…
Browse files Browse the repository at this point in the history
…motion#224

Date trailing the deflate content no longer corrupts the response bodies.

Improved messages for bad gzip footers.

Reduced handled gzip error log messages from error level to warn level.
  • Loading branch information
drbrain committed May 2, 2012
1 parent 34bf76a commit ec630de
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rdoc
Expand Up @@ -6,6 +6,8 @@
* Fixed typos in EXAMPLES and GUIDES. Pull Request #213 by Erkan Yilmaz.
* Fixed handling of a quoted content-disposition size. Pull Request #220 by
Jason Rust
* Mechanize now ignores a missing gzip footer like browsers do. Issue #224
by afhbl

=== 2.4

Expand Down
13 changes: 8 additions & 5 deletions lib/mechanize/http/agent.rb
Expand Up @@ -402,20 +402,23 @@ def content_encoding_gunzip body_io
zio.finish

return out_io
rescue Zlib::Error
log.error('unable to gunzip response, trying raw inflate') if log
rescue Zlib::Error => gz_error
log.warn "unable to gunzip response: #{gz_error} (#{gz_error.class})" if
log

body_io.rewind
body_io.read 10

begin
log.warn "trying raw inflate on response" if log
return inflate body_io, -Zlib::MAX_WBITS
rescue Zlib::Error => e
log.error("unable to gunzip response: #{e}") if log
log.error "unable to inflate response: #{e} (#{e.class})" if log
raise
end
ensure
zio.close if zio and not zio.closed?
# do not close a second time if we failed the first time
zio.close if zio and not (zio.closed? or gz_error)
body_io.close unless body_io.closed?
end

Expand Down Expand Up @@ -1115,7 +1118,7 @@ def inflate compressed, window_bits = nil
inflate.inflate chunk
end

out_io.write inflate.finish
inflate.finish

out_io
ensure
Expand Down
63 changes: 54 additions & 9 deletions test/test_mechanize_http_agent.rb
Expand Up @@ -874,13 +874,49 @@ def test_response_content_encoding_gzip_corrupt
assert_match %r%error handling content-encoding gzip:%, e.message
assert_match %r%Zlib%, e.message

assert_match %r%unable to gunzip response, trying raw inflate%, log.string
assert_match %r%unable to gunzip response:%, log.string
assert_match %r%unable to gunzip response: unexpected end of file%,
log.string
assert_match %r%unable to inflate response: buffer error%,
log.string

assert body_io.closed?
end

def test_response_content_encoding_gzip_corrupt_checksum
def test_response_content_encoding_gzip_checksum_corrupt_crc
log = StringIO.new
logger = Logger.new log
@agent.context.log = logger

@res.instance_variable_set :@header, 'content-encoding' => %w[gzip]
body_io = StringIO.new \
"\037\213\b\0002\002\225M\000\003+H,*\001\000\306p\017J\004\000\000\000"

body = @agent.response_content_encoding @res, body_io

assert_equal 'part', body.read

assert body_io.closed?

assert_match %r%invalid compressed data -- crc error%, log.string
end

def test_response_content_encoding_gzip_checksum_corrupt_length
log = StringIO.new
logger = Logger.new log
@agent.context.log = logger

@res.instance_variable_set :@header, 'content-encoding' => %w[gzip]
body_io = StringIO.new \
"\037\213\b\0002\002\225M\000\003+H,*\001\000\306p\017I\005\000\000\000"

body = @agent.response_content_encoding @res, body_io

assert body_io.closed?

assert_match %r%invalid compressed data -- length error%, log.string
end

def test_response_content_encoding_gzip_checksum_truncated
log = StringIO.new
logger = Logger.new log
@agent.context.log = logger
Expand All @@ -889,14 +925,11 @@ def test_response_content_encoding_gzip_corrupt_checksum
body_io = StringIO.new \
"\037\213\b\0002\002\225M\000\003+H,*\001\000\306p\017I\004\000\000"

e = assert_raises Mechanize::Error do
@agent.response_content_encoding @res, body_io
end
body = @agent.response_content_encoding @res, body_io

assert_match %r%error handling content-encoding gzip:%, e.message
assert_match %r%Zlib%, e.message
assert body_io.closed?

assert_match %r%unable to gunzip response, trying raw inflate%, log.string
assert_match %r%unable to gunzip response: footer is not found%, log.string
end

def test_response_content_encoding_gzip_empty
Expand Down Expand Up @@ -926,6 +959,18 @@ def test_response_content_encoding_gzip_encoding_bad
assert_equal Encoding::BINARY, content.encoding if have_encoding?
end

def test_response_content_encoding_gzip_no_footer
@res.instance_variable_set :@header, 'content-encoding' => %w[gzip]
body_io = StringIO.new \
"\037\213\b\0002\002\225M\000\003+H,*\001\000"

body = @agent.response_content_encoding @res, body_io

assert_equal 'part', body.read

assert body_io.closed?
end

def test_response_content_encoding_none
@res.instance_variable_set :@header, 'content-encoding' => %w[none]

Expand Down

0 comments on commit ec630de

Please sign in to comment.