net-http-persistent 4.0.5 → 4.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 182064ce89718e66d95177021a7005adeb6e1d4299925e90fc6ac2a537dc533d
4
- data.tar.gz: ef7588300c587a1f71e49496ed6131acdf3cad110fa6653acab3779f5f01e3ee
3
+ metadata.gz: 3e1c40dff68b8e70cac3630ca6b19ff70679fe7462974c835bb8638ab2b5dd5b
4
+ data.tar.gz: 95185bc4624e14eaae5b31e65a7b8e474a07f621020a5096966ccfec200bf6f7
5
5
  SHA512:
6
- metadata.gz: 14c95c55ea8c89616d13917ba1fb9b05253181fd7007cf5aa03ab03c8e9987e8d4dc936b21481bf37f810df5931994ea6e5dc2eb6c259ab6591f2cfa75bff24f
7
- data.tar.gz: e7560d360ac6b20b750a19f6b84c7e5f8656e44962fbb8223ae1295e18dea513456df99c268fa06c2909b9c7e1c4e96655b7055432032d1044187ce07a2ba40b
6
+ metadata.gz: 32089ec62a29518f3d6b1e9f1a1a677b65b1cc3b937506a9e3f985455f8c924b0c37c80516e9adc23420f8d25932607c4975cc042ec217bbd5bed2c626c2a57b
7
+ data.tar.gz: 28fc74bc92b2f63f752dfc8a2e86971f76b3cb064fe3647949005f9f1d7fa41d48d26122dd6f4c9d137d5255cd1b3dedc09ed779c937d12597fb9baba6c325e7
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ === 4.0.6 / 2024-12-04
2
+
3
+ Bug fixes:
4
+
5
+ * Allow ConnectionPool exceptions from checkout to bubble up to caller.
6
+
1
7
  === 4.0.5 / 2024-12-04
2
8
 
3
9
  Bug fixes:
data/README.rdoc CHANGED
@@ -1,7 +1,7 @@
1
1
  = net-http-persistent
2
2
 
3
3
  home :: https://github.com/drbrain/net-http-persistent
4
- rdoc :: https://rdoc.info/gems/net-http-persistent
4
+ rdoc :: https://rubydoc.info/gems/net-http-persistent
5
5
 
6
6
  == DESCRIPTION:
7
7
 
@@ -4,7 +4,7 @@ class Net::HTTP::Persistent::Pool < ConnectionPool # :nodoc:
4
4
  attr_reader :key # :nodoc:
5
5
 
6
6
  def initialize(options = {}, &block)
7
- super
7
+ super(**options, &block)
8
8
 
9
9
  @available = Net::HTTP::Persistent::TimedStackMulti.new(@size, &block)
10
10
  @key = "current-#{@available.object_id}"
@@ -1,5 +1,10 @@
1
1
  class Net::HTTP::Persistent::TimedStackMulti < ConnectionPool::TimedStack # :nodoc:
2
2
 
3
+ ##
4
+ # Detects if ConnectionPool 3.0+ is being used (needed for TimedStack subclass compatibility)
5
+
6
+ CP_USES_KEYWORD_ARGS = Gem::Version.new(ConnectionPool::VERSION) >= Gem::Version.new('3.0.0') # :nodoc:
7
+
3
8
  ##
4
9
  # Returns a new hash that has arrays for keys
5
10
  #
@@ -11,7 +16,11 @@ class Net::HTTP::Persistent::TimedStackMulti < ConnectionPool::TimedStack # :nod
11
16
  end
12
17
 
13
18
  def initialize(size = 0, &block)
14
- super
19
+ if CP_USES_KEYWORD_ARGS
20
+ super(size: size, &block)
21
+ else
22
+ super(size, &block)
23
+ end
15
24
 
16
25
  @enqueued = 0
17
26
  @ques = self.class.hash_of_arrays
@@ -63,7 +72,8 @@ class Net::HTTP::Persistent::TimedStackMulti < ConnectionPool::TimedStack # :nod
63
72
  if @created >= @max && @enqueued >= 1
64
73
  oldest, = @lru.first
65
74
  @lru.delete oldest
66
- @ques[oldest].pop
75
+ connection = @ques[oldest].pop
76
+ connection.close if connection.respond_to?(:close)
67
77
 
68
78
  @created -= 1
69
79
  end
@@ -1,6 +1,7 @@
1
1
  require 'net/http'
2
2
  require 'uri'
3
- require 'cgi' # for escaping
3
+ require 'cgi/escape'
4
+ require 'cgi/util' unless defined?(CGI::EscapeExt)
4
5
  require 'connection_pool'
5
6
 
6
7
  begin
@@ -47,9 +48,8 @@ autoload :OpenSSL, 'openssl'
47
48
  # # perform the POST, the URI is always required
48
49
  # response http.request post_uri, post
49
50
  #
50
- # Note that for GET, HEAD and other requests that do not have a body you want
51
- # to use URI#request_uri not URI#path. The request_uri contains the query
52
- # params which are sent in the body for other requests.
51
+ # Note that for GET, HEAD and other requests that do not have a body,
52
+ # it uses URI#request_uri as default to send query params
53
53
  #
54
54
  # == TLS/SSL
55
55
  #
@@ -182,7 +182,7 @@ class Net::HTTP::Persistent
182
182
  ##
183
183
  # The version of Net::HTTP::Persistent you are using
184
184
 
185
- VERSION = '4.0.5'
185
+ VERSION = '4.0.8'
186
186
 
187
187
  ##
188
188
  # Error class for errors raised by Net::HTTP::Persistent. Various
@@ -477,6 +477,13 @@ class Net::HTTP::Persistent
477
477
 
478
478
  attr_reader :verify_hostname
479
479
 
480
+
481
+ ##
482
+ # Sets whether to ignore end-of-file when reading a response body
483
+ # with Content-Length headers.
484
+
485
+ attr_accessor :ignore_eof
486
+
480
487
  ##
481
488
  # Creates a new Net::HTTP::Persistent.
482
489
  #
@@ -516,6 +523,7 @@ class Net::HTTP::Persistent
516
523
  @max_retries = 1
517
524
  @socket_options = []
518
525
  @ssl_generation = 0 # incremented when SSL session variables change
526
+ @ignore_eof = nil
519
527
 
520
528
  @socket_options << [Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1] if
521
529
  Socket.const_defined? :TCP_NODELAY
@@ -631,47 +639,50 @@ class Net::HTTP::Persistent
631
639
 
632
640
  connection = @pool.checkout net_http_args
633
641
 
634
- http = connection.http
642
+ begin
643
+ http = connection.http
635
644
 
636
- connection.ressl @ssl_generation if
637
- connection.ssl_generation != @ssl_generation
645
+ connection.ressl @ssl_generation if
646
+ connection.ssl_generation != @ssl_generation
638
647
 
639
- if not http.started? then
640
- ssl http if use_ssl
641
- start http
642
- elsif expired? connection then
643
- reset connection
644
- end
648
+ if not http.started? then
649
+ ssl http if use_ssl
650
+ start http
651
+ elsif expired? connection then
652
+ reset connection
653
+ end
645
654
 
646
- http.keep_alive_timeout = @idle_timeout if @idle_timeout
647
- http.max_retries = @max_retries if http.respond_to?(:max_retries=)
648
- http.read_timeout = @read_timeout if @read_timeout
649
- http.write_timeout = @write_timeout if
650
- @write_timeout && http.respond_to?(:write_timeout=)
655
+ http.ignore_eof = @ignore_eof if @ignore_eof
656
+ http.keep_alive_timeout = @idle_timeout if @idle_timeout
657
+ http.max_retries = @max_retries if http.respond_to?(:max_retries=)
658
+ http.read_timeout = @read_timeout if @read_timeout
659
+ http.write_timeout = @write_timeout if
660
+ @write_timeout && http.respond_to?(:write_timeout=)
661
+
662
+ return yield connection
663
+ rescue Errno::ECONNREFUSED
664
+ if http.proxy?
665
+ address = http.proxy_address
666
+ port = http.proxy_port
667
+ else
668
+ address = http.address
669
+ port = http.port
670
+ end
651
671
 
652
- return yield connection
653
- rescue Errno::ECONNREFUSED
654
- if http.proxy?
655
- address = http.proxy_address
656
- port = http.proxy_port
657
- else
658
- address = http.address
659
- port = http.port
660
- end
672
+ raise Error, "connection refused: #{address}:#{port}"
673
+ rescue Errno::EHOSTDOWN
674
+ if http.proxy?
675
+ address = http.proxy_address
676
+ port = http.proxy_port
677
+ else
678
+ address = http.address
679
+ port = http.port
680
+ end
661
681
 
662
- raise Error, "connection refused: #{address}:#{port}"
663
- rescue Errno::EHOSTDOWN
664
- if http.proxy?
665
- address = http.proxy_address
666
- port = http.proxy_port
667
- else
668
- address = http.address
669
- port = http.port
682
+ raise Error, "host down: #{address}:#{port}"
683
+ ensure
684
+ @pool.checkin net_http_args
670
685
  end
671
-
672
- raise Error, "host down: #{address}:#{port}"
673
- ensure
674
- @pool.checkin net_http_args
675
686
  end
676
687
 
677
688
  ##
@@ -825,7 +836,7 @@ class Net::HTTP::Persistent
825
836
  @proxy_connection_id = [nil, *@proxy_args].join ':'
826
837
 
827
838
  if @proxy_uri.query then
828
- @no_proxy = CGI.parse(@proxy_uri.query)['no_proxy'].join(',').downcase.split(',').map { |x| x.strip }.reject { |x| x.empty? }
839
+ @no_proxy = URI.decode_www_form(@proxy_uri.query).filter_map { |k, v| v if k == 'no_proxy' }.join(',').downcase.split(',').map { |x| x.strip }.reject { |x| x.empty? }
829
840
  end
830
841
  end
831
842
 
@@ -996,7 +1007,8 @@ class Net::HTTP::Persistent
996
1007
  end
997
1008
 
998
1009
  ##
999
- # Shuts down all connections
1010
+ # Shuts down all connections. Attempting to checkout a connection after
1011
+ # shutdown will raise an error.
1000
1012
  #
1001
1013
  # *NOTE*: Calling shutdown for can be dangerous!
1002
1014
  #
@@ -1007,6 +1019,17 @@ class Net::HTTP::Persistent
1007
1019
  @pool.shutdown { |http| http.finish }
1008
1020
  end
1009
1021
 
1022
+ ##
1023
+ # Discard all existing connections. Subsequent checkouts will create
1024
+ # new connections as needed.
1025
+ #
1026
+ # If any thread is still using a connection it may cause an error! Call
1027
+ # #reload when you are completely done making requests!
1028
+
1029
+ def reload
1030
+ @pool.reload { |http| http.finish }
1031
+ end
1032
+
1010
1033
  ##
1011
1034
  # Enables SSL on +connection+
1012
1035
 
@@ -80,7 +80,7 @@ class TestNetHttpPersistent < Minitest::Test
80
80
  :read_timeout, :open_timeout, :keep_alive_timeout
81
81
  attr_accessor :ciphers, :ssl_timeout, :ssl_version, :min_version,
82
82
  :max_version, :verify_depth, :verify_mode, :cert_store,
83
- :ca_file, :ca_path, :cert, :key
83
+ :ca_file, :ca_path, :cert, :key, :ignore_eof
84
84
  attr_reader :req, :debug_output
85
85
  def initialize
86
86
  @started, @finished = 0, 0
@@ -280,6 +280,16 @@ class TestNetHttpPersistent < Minitest::Test
280
280
  assert_same used, stored
281
281
  end
282
282
 
283
+ def test_connection_for_exhaustion
284
+ @http = Net::HTTP::Persistent.new pool_size: 0
285
+
286
+ assert_raises Timeout::Error do
287
+ @http.connection_for @uri do |c|
288
+ assert_same nil, c
289
+ end
290
+ end
291
+ end
292
+
283
293
  def test_connection_for_cached
284
294
  cached = basic_connection
285
295
  cached.http.start
@@ -993,7 +1003,7 @@ class TestNetHttpPersistent < Minitest::Test
993
1003
 
994
1004
  # There's some roounding issue on jruby preventing this from passing
995
1005
  unless RUBY_PLATFORM == "java"
996
- assert_in_delta Time.now, c.last_use
1006
+ assert_in_delta Time.now, c.last_use, 0.003
997
1007
  end
998
1008
 
999
1009
  assert_equal 1, c.requests
@@ -1255,6 +1265,17 @@ class TestNetHttpPersistent < Minitest::Test
1255
1265
  refute c2.http.finished?, 'present generation connection must not be finished'
1256
1266
  end
1257
1267
 
1268
+ def test_reload
1269
+ c = connection
1270
+
1271
+ @http.reload
1272
+
1273
+ c2 = connection
1274
+
1275
+ assert c.http.finished?, 'last-generation connection must be finished'
1276
+ refute c2.http.finished?, 'present generation connection must not be finished'
1277
+ end
1278
+
1258
1279
  def test_ssl
1259
1280
  skip 'OpenSSL is missing' unless HAVE_OPENSSL
1260
1281
 
@@ -1509,4 +1530,22 @@ class TestNetHttpPersistent < Minitest::Test
1509
1530
  connection.close
1510
1531
  end
1511
1532
  end
1533
+
1534
+ def test_ignore_eof
1535
+ @http.ignore_eof = true
1536
+
1537
+ connection
1538
+
1539
+ @http.connection_for @uri do |c|
1540
+ assert c.http.ignore_eof
1541
+ end
1542
+
1543
+ @http.ignore_eof = false
1544
+
1545
+ connection
1546
+
1547
+ @http.connection_for @uri do |c|
1548
+ assert !c.http.ignore_eof
1549
+ end
1550
+ end
1512
1551
  end
@@ -4,10 +4,15 @@ require 'net/http/persistent'
4
4
  class TestNetHttpPersistentTimedStackMulti < Minitest::Test
5
5
 
6
6
  class Connection
7
- attr_reader :host
7
+ attr_reader :host, :closed
8
8
 
9
9
  def initialize(host)
10
10
  @host = host
11
+ @closed = false
12
+ end
13
+
14
+ def close
15
+ @closed = true
11
16
  end
12
17
  end
13
18
 
@@ -24,7 +29,7 @@ class TestNetHttpPersistentTimedStackMulti < Minitest::Test
24
29
 
25
30
  assert_empty stack
26
31
 
27
- stack.push connection_args: popped
32
+ stack.push popped, connection_args: 'default'
28
33
 
29
34
  refute_empty stack
30
35
  end
@@ -38,7 +43,7 @@ class TestNetHttpPersistentTimedStackMulti < Minitest::Test
38
43
 
39
44
  assert_equal 0, stack.length
40
45
 
41
- stack.push connection_args: popped
46
+ stack.push popped, connection_args: 'default'
42
47
 
43
48
  assert_equal 1, stack.length
44
49
  end
@@ -57,7 +62,7 @@ class TestNetHttpPersistentTimedStackMulti < Minitest::Test
57
62
  @stack.pop timeout: 0
58
63
  end
59
64
 
60
- assert_match 'Waited 0 sec', e.message
65
+ assert_includes e.message, 'Waited 0 sec'
61
66
  end
62
67
 
63
68
  def test_pop_full
@@ -69,6 +74,18 @@ class TestNetHttpPersistentTimedStackMulti < Minitest::Test
69
74
  assert_empty stack
70
75
  end
71
76
 
77
+ def test_pop_closes_extra_connections
78
+ stack = Net::HTTP::Persistent::TimedStackMulti.new(1) { |host| Connection.new(host) }
79
+
80
+ a_conn = stack.pop connection_args: 'a.example'
81
+ stack.push a_conn, connection_args: 'a.example'
82
+
83
+ b_conn = stack.pop connection_args: 'b.example'
84
+
85
+ assert a_conn.closed
86
+ refute b_conn.closed
87
+ end
88
+
72
89
  def test_pop_wait
73
90
  thread = Thread.start do
74
91
  @stack.pop
@@ -96,7 +113,7 @@ class TestNetHttpPersistentTimedStackMulti < Minitest::Test
96
113
 
97
114
  conn = stack.pop
98
115
 
99
- stack.push connection_args: conn
116
+ stack.push conn, connection_args: 'default'
100
117
 
101
118
  refute_empty stack
102
119
  end
@@ -108,14 +125,16 @@ class TestNetHttpPersistentTimedStackMulti < Minitest::Test
108
125
  called << object
109
126
  end
110
127
 
111
- @stack.push connection_args: Object.new
128
+ obj = Object.new
129
+ @stack.push obj, connection_args: 'default'
112
130
 
113
131
  refute_empty called
114
132
  assert_empty @stack
115
133
  end
116
134
 
117
135
  def test_shutdown
118
- @stack.push connection_args: Object.new
136
+ obj = Object.new
137
+ @stack.push obj, connection_args: 'default'
119
138
 
120
139
  called = []
121
140
 
metadata CHANGED
@@ -1,29 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-http-persistent
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.5
4
+ version: 4.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Hodel
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: connection_pool
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '2.2'
18
+ version: 2.2.4
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '4'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
23
25
  requirements:
24
- - - "~>"
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: 2.2.4
29
+ - - "<"
25
30
  - !ruby/object:Gem::Version
26
- version: '2.2'
31
+ version: '4'
27
32
  description: |-
28
33
  Manages persistent connections using Net::HTTP including a thread pool for
29
34
  connecting to multiple hosts.
@@ -63,7 +68,6 @@ licenses:
63
68
  - MIT
64
69
  metadata:
65
70
  homepage_uri: https://github.com/drbrain/net-http-persistent
66
- post_install_message:
67
71
  rdoc_options:
68
72
  - "--main"
69
73
  - README.rdoc
@@ -80,8 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
84
  - !ruby/object:Gem::Version
81
85
  version: '0'
82
86
  requirements: []
83
- rubygems_version: 3.0.3.1
84
- signing_key:
87
+ rubygems_version: 4.0.3
85
88
  specification_version: 4
86
89
  summary: Manages persistent connections using Net::HTTP including a thread pool for
87
90
  connecting to multiple hosts