[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]