From 0a013de42dd1d236ba7ad5f34148393620a1622b Mon Sep 17 00:00:00 2001
From: Kazuki Yamaguchi <k@rhe.jp>
Date: Thu, 29 Apr 2021 20:42:33 +0900
Subject: [PATCH] Reset keep_alive timer on new connection

The last_communicated timestamp is for HTTP persistent connection, to
decide whether the current TCP connection may be reused for the
subsequent requests or not. Naturally, the timer must be reset if the
connection is recreated since it is no longer relevant.
---
 lib/net/http.rb            |  1 +
 test/net/http/test_http.rb | 24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/lib/net/http.rb b/lib/net/http.rb
index 862f88dd..d0203b97 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -1048,6 +1048,7 @@ def connect
                                write_timeout: @write_timeout,
                                continue_timeout: @continue_timeout,
                                debug_output: @debug_output)
+      @last_communicated = nil
       on_connect
     rescue => exception
       if s
diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb
index 60b6d51f..1d5d1790 100644
--- a/test/net/http/test_http.rb
+++ b/test/net/http/test_http.rb
@@ -1141,6 +1141,30 @@ def test_keep_alive_get_auto_retry
     }
   end
 
+  def test_keep_alive_reset_on_new_connection
+    # Using WEBrick's debug log output on accepting connection:
+    #
+    #   "[2021-04-29 20:36:46] DEBUG accept: 127.0.0.1:50674\n"
+    @log_tester = nil
+    @server.logger.level = WEBrick::BasicLog::DEBUG
+
+    start {|http|
+      res = http.get('/')
+      http.keep_alive_timeout = 1
+      assert_kind_of Net::HTTPResponse, res
+      assert_kind_of String, res.body
+      http.finish
+      assert_equal 1, @log.grep(/accept/i).size
+
+      sleep 1.5
+      http.start
+      res = http.get('/')
+      assert_kind_of Net::HTTPResponse, res
+      assert_kind_of String, res.body
+      assert_equal 2, @log.grep(/accept/i).size
+    }
+  end
+
   class MockSocket
     attr_reader :count
     def initialize(success_after: nil)