Skip to content

Commit 0428107

Browse files
authored
Merge branch 'master' into reload-pool
2 parents df81992 + fad1632 commit 0428107

File tree

9 files changed

+206
-25
lines changed

9 files changed

+206
-25
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
ruby: [2.4, 2.5, 2.6, 2.7, '3.0', 3.1, jruby-9.2]
16-
os: [ubuntu-20.04, windows-2019]
15+
ruby: [2.4, 2.5, 2.6, 2.7, '3.0', 3.1, 3.2, jruby-9.2]
16+
os: [ubuntu-20.04, windows-2022]
1717
include:
1818
- { ruby: 3.1, os: ubuntu-20.04, matrix: pipeline }
1919

@@ -23,13 +23,12 @@ jobs:
2323
CI_MATRIX: ${{ matrix.matrix }}
2424

2525
steps:
26-
- uses: actions/checkout@v2
26+
- uses: actions/checkout@v3
2727

2828
- name: Set up Ruby
2929
uses: ruby/setup-ruby@v1
3030
with:
3131
ruby-version: ${{ matrix.ruby }}
32-
rubygems: 3.3.6
3332
bundler-cache: true
3433

3534
- name: Test things

History.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
=== 4.0.5 / 2024-12-04
2+
3+
Bug fixes:
4+
5+
* Allow setting extra_chain_cert=
6+
7+
=== 4.0.4 / 2024-09-09
8+
9+
Bug fixes:
10+
11+
* Allow setting verify_hostname to false
12+
13+
=== 4.0.3 / 2024-09-09
14+
15+
Bug fixes:
16+
17+
* Handle Net::HTTP#verify_hostname was added in Ruby 3.0 or later. #120
18+
19+
=== 4.0.2 / 2023-03-29
20+
21+
Bug fixes:
22+
23+
* Fix compatibility with `connection_pool 2.4+`
24+
125
=== 4.0.1 / 2021-01-12
226

327
Bug fixes:

README.rdoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
= net-http-persistent
22

33
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
55

66
== DESCRIPTION:
77

lib/net/http/persistent.rb

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
# #ca_path :: Directory with certificate-authorities
6666
# #cert_store :: An SSL certificate store
6767
# #ciphers :: List of SSl ciphers allowed
68+
# #extra_chain_cert :: Extra certificates to be added to the certificate chain
6869
# #private_key :: The client's SSL private key
6970
# #reuse_ssl_sessions :: Reuse a previously opened SSL session for a new
7071
# connection
@@ -73,6 +74,8 @@
7374
# #verify_callback :: For server certificate verification
7475
# #verify_depth :: Depth of certificate verification
7576
# #verify_mode :: How connections should be verified
77+
# #verify_hostname :: Use hostname verification for server certificate
78+
# during the handshake
7679
#
7780
# == Proxies
7881
#
@@ -179,7 +182,7 @@ class Net::HTTP::Persistent
179182
##
180183
# The version of Net::HTTP::Persistent you are using
181184

182-
VERSION = '4.0.1'
185+
VERSION = '4.0.5'
183186

184187
##
185188
# Error class for errors raised by Net::HTTP::Persistent. Various
@@ -270,6 +273,11 @@ def self.detect_idle_timeout uri, max = 10
270273

271274
attr_reader :ciphers
272275

276+
##
277+
# Extra certificates to be added to the certificate chain
278+
279+
attr_reader :extra_chain_cert
280+
273281
##
274282
# Sends debug_output to this IO via Net::HTTP#set_debug_output.
275283
#
@@ -454,6 +462,21 @@ def self.detect_idle_timeout uri, max = 10
454462

455463
attr_reader :verify_mode
456464

465+
##
466+
# HTTPS verify_hostname.
467+
#
468+
# If a client sets this to true and enables SNI with SSLSocket#hostname=,
469+
# the hostname verification on the server certificate is performed
470+
# automatically during the handshake using
471+
# OpenSSL::SSL.verify_certificate_identity().
472+
#
473+
# You can set +verify_hostname+ as true to use hostname verification
474+
# during the handshake.
475+
#
476+
# NOTE: This works with Ruby > 3.0.
477+
478+
attr_reader :verify_hostname
479+
457480
##
458481
# Creates a new Net::HTTP::Persistent.
459482
#
@@ -513,6 +536,7 @@ def initialize name: nil, proxy: nil, pool_size: DEFAULT_POOL_SIZE
513536
@verify_callback = nil
514537
@verify_depth = nil
515538
@verify_mode = nil
539+
@verify_hostname = nil
516540
@cert_store = nil
517541

518542
@generation = 0 # incremented when proxy URI changes
@@ -574,6 +598,21 @@ def ciphers= ciphers
574598
reconnect_ssl
575599
end
576600

601+
if Net::HTTP.method_defined?(:extra_chain_cert=)
602+
##
603+
# Extra certificates to be added to the certificate chain.
604+
# It is only supported starting from Net::HTTP version 0.1.1
605+
def extra_chain_cert= extra_chain_cert
606+
@extra_chain_cert = extra_chain_cert
607+
608+
reconnect_ssl
609+
end
610+
else
611+
def extra_chain_cert= _extra_chain_cert
612+
raise "extra_chain_cert= is not supported by this version of Net::HTTP"
613+
end
614+
end
615+
577616
##
578617
# Creates a new connection for +uri+
579618

@@ -612,13 +651,23 @@ def connection_for uri
612651

613652
return yield connection
614653
rescue Errno::ECONNREFUSED
615-
address = http.proxy_address || http.address
616-
port = http.proxy_port || http.port
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
617661

618662
raise Error, "connection refused: #{address}:#{port}"
619663
rescue Errno::EHOSTDOWN
620-
address = http.proxy_address || http.address
621-
port = http.proxy_port || http.port
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
622671

623672
raise Error, "host down: #{address}:#{port}"
624673
ensure
@@ -982,8 +1031,10 @@ def ssl connection
9821031
connection.min_version = @min_version if @min_version
9831032
connection.max_version = @max_version if @max_version
9841033

985-
connection.verify_depth = @verify_depth
986-
connection.verify_mode = @verify_mode
1034+
connection.verify_depth = @verify_depth
1035+
connection.verify_mode = @verify_mode
1036+
connection.verify_hostname = @verify_hostname if
1037+
@verify_hostname != nil && connection.respond_to?(:verify_hostname=)
9871038

9881039
if OpenSSL::SSL::VERIFY_PEER == OpenSSL::SSL::VERIFY_NONE and
9891040
not Object.const_defined?(:I_KNOW_THAT_OPENSSL_VERIFY_PEER_EQUALS_VERIFY_NONE_IS_WRONG) then
@@ -1025,6 +1076,10 @@ def ssl connection
10251076
connection.key = @private_key
10261077
end
10271078

1079+
if defined?(@extra_chain_cert) and @extra_chain_cert
1080+
connection.extra_chain_cert = @extra_chain_cert
1081+
end
1082+
10281083
connection.cert_store = if @cert_store then
10291084
@cert_store
10301085
else
@@ -1092,6 +1147,15 @@ def verify_mode= verify_mode
10921147
reconnect_ssl
10931148
end
10941149

1150+
##
1151+
# Sets the HTTPS verify_hostname.
1152+
1153+
def verify_hostname= verify_hostname
1154+
@verify_hostname = verify_hostname
1155+
1156+
reconnect_ssl
1157+
end
1158+
10951159
##
10961160
# SSL verification callback.
10971161

@@ -1104,4 +1168,3 @@ def verify_callback= callback
11041168

11051169
require_relative 'persistent/connection'
11061170
require_relative 'persistent/pool'
1107-

lib/net/http/persistent/connection.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def finish
2525
ensure
2626
reset
2727
end
28+
alias_method :close, :finish
2829

2930
def reset
3031
@last_use = Net::HTTP::Persistent::EPOCH

lib/net/http/persistent/pool.rb

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,32 @@ def initialize(options = {}, &block)
1111
end
1212

1313
def checkin net_http_args
14-
stack = Thread.current[@key][net_http_args] ||= []
14+
if net_http_args.is_a?(Hash) && net_http_args.size == 1 && net_http_args[:force]
15+
# ConnectionPool 2.4+ calls `checkin(force: true)` after fork.
16+
# When this happens, we should remove all connections from Thread.current
17+
if stacks = Thread.current[@key]
18+
stacks.each do |http_args, connections|
19+
connections.each do |conn|
20+
@available.push conn, connection_args: http_args
21+
end
22+
connections.clear
23+
end
24+
end
25+
else
26+
stack = Thread.current[@key][net_http_args] ||= []
1527

16-
raise ConnectionPool::Error, 'no connections are checked out' if
17-
stack.empty?
28+
raise ConnectionPool::Error, 'no connections are checked out' if
29+
stack.empty?
1830

19-
conn = stack.pop
31+
conn = stack.pop
2032

21-
if stack.empty?
22-
@available.push conn, connection_args: net_http_args
33+
if stack.empty?
34+
@available.push conn, connection_args: net_http_args
2335

24-
Thread.current[@key].delete(net_http_args)
25-
Thread.current[@key] = nil if Thread.current[@key].empty?
36+
Thread.current[@key].delete(net_http_args)
37+
Thread.current[@key] = nil if Thread.current[@key].empty?
38+
end
2639
end
27-
2840
nil
2941
end
3042

lib/net/http/persistent/timed_stack_multi.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ def try_create options = {} # :nodoc:
6363
if @created >= @max && @enqueued >= 1
6464
oldest, = @lru.first
6565
@lru.delete oldest
66-
@ques[oldest].pop
66+
connection = @ques[oldest].pop
67+
connection.close if connection.respond_to?(:close)
6768

6869
@created -= 1
6970
end

test/test_net_http_persistent.rb

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ def proxy_address
116116
end
117117
def proxy_port
118118
end
119+
def proxy?
120+
false
121+
end
119122
end
120123

121124
def basic_connection
@@ -244,6 +247,14 @@ def test_ciphers_equals
244247
assert_equal 1, @http.ssl_generation
245248
end
246249

250+
def test_extra_chain_cert_equals
251+
skip 'extra_chain_cert is not supported by Net::HTTP' unless Net::HTTP.method_defined?(:extra_chain_cert)
252+
@http.extra_chain_cert = :extra_chain_cert
253+
254+
assert_equal :extra_chain_cert, @http.extra_chain_cert
255+
assert_equal 1, @http.ssl_generation
256+
end
257+
247258
def test_connection_for
248259
@http.open_timeout = 123
249260
@http.read_timeout = 321
@@ -1267,6 +1278,7 @@ def test_ssl
12671278
assert_equal OpenSSL::SSL::VERIFY_PEER, c.verify_mode
12681279
assert_kind_of OpenSSL::X509::Store, c.cert_store
12691280
assert_nil c.verify_callback
1281+
assert_nil c.verify_hostname if c.respond_to?(:verify_hostname)
12701282
end
12711283

12721284
def test_ssl_ca_file
@@ -1350,6 +1362,49 @@ def test_ssl_verify_mode
13501362
assert_equal OpenSSL::SSL::VERIFY_NONE, c.verify_mode
13511363
end
13521364

1365+
def test_ssl_enable_verify_hostname
1366+
skip 'OpenSSL is missing' unless HAVE_OPENSSL
1367+
1368+
@http.verify_hostname = true
1369+
c = Net::HTTP.new 'localhost', 80
1370+
1371+
skip 'net/http doesn\'t provide verify_hostname= method' unless
1372+
c.respond_to?(:verify_hostname=)
1373+
1374+
@http.ssl c
1375+
1376+
assert c.use_ssl?
1377+
assert c.verify_hostname
1378+
end
1379+
1380+
def test_ssl_disable_verify_hostname
1381+
skip 'OpenSSL is missing' unless HAVE_OPENSSL
1382+
1383+
@http.verify_hostname = false
1384+
c = Net::HTTP.new 'localhost', 80
1385+
1386+
skip 'net/http doesn\'t provide verify_hostname= method' unless
1387+
c.respond_to?(:verify_hostname=)
1388+
1389+
@http.ssl c
1390+
1391+
assert c.use_ssl?
1392+
assert c.verify_hostname == false
1393+
end
1394+
1395+
def test_ssl_extra_chain_cert
1396+
skip 'OpenSSL is missing' unless HAVE_OPENSSL
1397+
skip 'extra_chain_cert is not supported by Net::HTTP' unless Net::HTTP.method_defined?(:extra_chain_cert)
1398+
1399+
@http.extra_chain_cert = :extra_chain_cert
1400+
c = Net::HTTP.new 'localhost', 80
1401+
1402+
@http.ssl c
1403+
1404+
assert c.use_ssl?
1405+
assert_equal :extra_chain_cert, c.extra_chain_cert
1406+
end
1407+
13531408
def test_ssl_warning
13541409
skip 'OpenSSL is missing' unless HAVE_OPENSSL
13551410

@@ -1455,5 +1510,14 @@ def test_verify_mode_equals
14551510
assert_equal 1, @http.ssl_generation
14561511
end
14571512

1458-
end
1513+
def test_connection_pool_after_fork
1514+
# ConnectionPool 2.4+ calls `checkin(force: true)` after fork
1515+
@http.pool.checkin(force: true)
14591516

1517+
@http.pool.checkout ['example.com', 80, nil, nil, nil, nil]
1518+
@http.pool.checkin(force: true)
1519+
@http.pool.reload do |connection|
1520+
connection.close
1521+
end
1522+
end
1523+
end

0 commit comments

Comments
 (0)