From 5b42d75812c05266a6a4a25d7ec90c60cd71167c Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 7 Oct 2026 20:19:09 +0900 Subject: [PATCH] Stop loading resolv from net/http Net::HTTP required the whole DNS resolver, which also reads the system DNS configuration at load time, only to match Resolv::IPv4::Regex and Resolv::IPv6::Regex when deciding whether to send SNI. Use the same inlined regexps as the copy vendored in RubyGems, so that the two stay identical. Co-Authored-By: Claude Opus 5.5 --- lib/net/http.rb | 26 ++++++++++++++++++++++++-- test/net/http/test_http.rb | 7 +++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/net/http.rb b/lib/net/http.rb index 0802f125..82255f2a 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -22,7 +22,6 @@ require 'net/protocol' require 'uri' -require 'resolv' autoload :OpenSSL, 'openssl' module Net #:nodoc: @@ -1539,6 +1538,29 @@ def use_ssl=(flag) SSL_IVNAMES = SSL_ATTRIBUTES.map { |a| "@#{a}".to_sym }.freeze # :nodoc: + # Resolv::IPv4::Regex and Resolv::IPv6::Regex, copied from resolv 0.7.1 rather + # than required, so that net/http does not load a DNS resolver just to keep an + # IP address literal out of the Server Name Indication. + # https://github.com/ruby/resolv/blob/v0.7.1/lib/resolv.rb + ipv4_octet = /0|1(?:[0-9][0-9]?)?|2(?:[0-4][0-9]?|5[0-5]?|[6-9])?|[3-9][0-9]?/ + hex16 = /[0-9A-Fa-f]{1,4}/ + hex16_group = /(?:#{hex16}(?::#{hex16})*)?/ + dotted_quad = /\d+\.\d+\.\d+\.\d+/ + zone_id = /%[-0-9A-Za-z._~]+/ + + IPV4_ADDRESS = /\A(?:#{ipv4_octet})\.(?:#{ipv4_octet})\.(?:#{ipv4_octet})\.(?:#{ipv4_octet})\z/ # :nodoc: + + IPV6_ADDRESS = /\A(?: + (?:#{hex16}:){7}#{hex16} # a:b:c:d:e:f:g:h + | #{hex16_group}::#{hex16_group} # a::b + | (?:#{hex16}:){6}#{dotted_quad} # a:b:c:d:e:f:w.x.y.z + | #{hex16_group}::(?:#{hex16}:)*#{dotted_quad} # a::b:w.x.y.z + | [Ff][Ee]80(?::#{hex16}){7}#{zone_id} # fe80:b:c:d:e:f:g:h%em1 + | [Ff][Ee]80:(?:#{hex16_group}::#{hex16_group}|:#{hex16_group})?:#{hex16}#{zone_id} # fe80::b%em1 + )\z/x # :nodoc: + + private_constant :IPV4_ADDRESS, :IPV6_ADDRESS + # Sets or returns the path to a CA certification file in PEM format. attr_accessor :ca_file @@ -1738,7 +1760,7 @@ def connect # Server Name Indication (SNI) RFC 3546/6066 case @address - when Resolv::IPv4::Regex, Resolv::IPv6::Regex + when IPV4_ADDRESS, IPV6_ADDRESS # don't set SNI, as IP addresses in SNI is not valid # per RFC 6066, section 3. diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb index 590f8a2f..8a306920 100644 --- a/test/net/http/test_http.rb +++ b/test/net/http/test_http.rb @@ -266,6 +266,13 @@ def test_default_configuration Net::HTTP.default_configuration = nil end + def test_require_does_not_load_resolv + assert_separately([], <<~'RUBY') + require 'net/http' + assert_nil defined?(Resolv) + RUBY + end + end module TestNetHTTP_version_1_1_methods