ruby-changes:71777
From: Jeremy <ko1@a...>
Date: Wed, 20 Apr 2022 10:22:26 +0900 (JST)
Subject: [ruby-changes:71777] 90ccc5674a (master): [ruby/net-http] Add ignore_eof access to HTTP and HTTPResponse
https://git.ruby-lang.org/ruby.git/commit/?id=90ccc5674a From 90ccc5674affb64036ca86f566c8650f654fc0f6 Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@j...> Date: Mon, 1 Mar 2021 12:59:21 -0800 Subject: [ruby/net-http] Add ignore_eof access to HTTP and HTTPResponse The ignore_eof setting on HTTPResponse makes it so an EOFError is raised when reading bodies with a defined Content-Length, if the body read was truncated due to the socket be closed. The ignore_eof setting on HTTP sets the values used in responses that are created by the object. For backwards compatibility, the default is for both settings is true. However, unless you are specifically tested for and handling truncated responses, it's a good idea to set ignore_eof to false so that errors are raised for truncated responses, instead of those errors silently being ignored. Fixes [Bug #14972] https://github.com/ruby/net-http/commit/4d47e34995 --- lib/net/http.rb | 6 ++++++ lib/net/http/response.rb | 7 ++++++- test/net/http/test_http.rb | 30 ++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/net/http.rb b/lib/net/http.rb index 5e64e38665..dc8ed051f0 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -699,6 +699,7 @@ module Net #:nodoc: https://github.com/ruby/ruby/blob/trunk/lib/net/http.rb#L699 @max_retries = 1 @debug_output = nil @response_body_encoding = false + @ignore_eof = true @proxy_from_env = false @proxy_uri = nil @@ -839,6 +840,10 @@ module Net #:nodoc: https://github.com/ruby/ruby/blob/trunk/lib/net/http.rb#L840 # The default value is 2 seconds. attr_accessor :keep_alive_timeout + # Whether to ignore EOF when reading response bodies with defined + # Content-Length headers. For backwards compatibility, the default is true. + attr_accessor :ignore_eof + # Returns true if the HTTP session has been started. def started? @started @@ -1606,6 +1611,7 @@ module Net #:nodoc: https://github.com/ruby/ruby/blob/trunk/lib/net/http.rb#L1611 res = HTTPResponse.read_new(@socket) res.decode_content = req.decode_content res.body_encoding = @response_body_encoding + res.ignore_eof = @ignore_eof end while res.kind_of?(HTTPInformation) res.uri = req.uri diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb index 9cedbdbbfe..f8b522f1ff 100644 --- a/lib/net/http/response.rb +++ b/lib/net/http/response.rb @@ -85,6 +85,7 @@ class Net::HTTPResponse https://github.com/ruby/ruby/blob/trunk/lib/net/http/response.rb#L85 @uri = nil @decode_content = false @body_encoding = false + @ignore_eof = true end # The HTTP version supported by the server. @@ -119,6 +120,10 @@ class Net::HTTPResponse https://github.com/ruby/ruby/blob/trunk/lib/net/http/response.rb#L120 @body_encoding = value end + # Whether to ignore EOF when reading bodies with a specified Content-Length + # header. + attr_accessor :ignore_eof + def inspect "#<#{self.class} #{@code} #{@message} readbody=#{@read}>" end @@ -459,7 +464,7 @@ class Net::HTTPResponse https://github.com/ruby/ruby/blob/trunk/lib/net/http/response.rb#L464 clen = content_length() if clen - @socket.read clen, dest, true # ignore EOF + @socket.read clen, dest, @ignore_eof return end clen = range_length() diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb index 4725a79147..e9471273f4 100644 --- a/test/net/http/test_http.rb +++ b/test/net/http/test_http.rb @@ -1348,3 +1348,33 @@ class TestNetHTTPForceEncoding < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/net/http/test_http.rb#L1348 assert_equal(Encoding::UTF_8, res.body.encoding) end end + +class TestNetHTTPPartialResponse < Test::Unit::TestCase + CONFIG = { + 'host' => '127.0.0.1', + 'proxy_host' => nil, + 'proxy_port' => nil, + } + + include TestNetHTTPUtils + + def test_partial_response + str = "0123456789" + @server.mount_proc('/') do |req, res| + res.status = 200 + res['Content-Type'] = 'text/plain' + + res.body = str + res['Content-Length'] = str.length + 1 + end + @server.mount_proc('/show_ip') { |req, res| res.body = req.remote_ip } + + http = Net::HTTP.new(config('host'), config('port')) + res = http.get('/') + assert_equal(str, res.body) + + http = Net::HTTP.new(config('host'), config('port')) + http.ignore_eof = false + assert_raise(EOFError) {http.get('/')} + end +end -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/