summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-03-01 12:59:21 -0800
committergit <svn-admin@ruby-lang.org>2022-04-20 10:22:06 +0900
commit90ccc5674affb64036ca86f566c8650f654fc0f6 (patch)
tree0d18cee05d0ba91778b48dc818b6477b076eb6c2
parentfada4d24f9acd98f1e289913f6eea584d281fb42 (diff)
[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
-rw-r--r--lib/net/http.rb6
-rw-r--r--lib/net/http/response.rb7
-rw-r--r--test/net/http/test_http.rb30
3 files changed, 42 insertions, 1 deletions
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:
@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:
# 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:
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
@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
@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
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
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