Skip to content

Commit ce5c9b4

Browse files
authored
Merge branch 'master' into baweaver/exceptions-pattern-matching
2 parents bd4d522 + 8e08f34 commit ce5c9b4

12 files changed

Lines changed: 200 additions & 44 deletions

File tree

.document

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
BSDL
2+
COPYING
3+
README.md
4+
doc/
5+
lib/

.github/workflows/push_gem.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323

2424
steps:
2525
- name: Harden Runner
26-
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
26+
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
2727
with:
2828
egress-policy: audit
2929

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
88
with:
99
engine: cruby
10-
min_version: 2.6
10+
min_version: 2.7
1111

1212
test:
1313
needs: ruby-versions

lib/net/http.rb

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ class HTTPHeaderSyntaxError < StandardError; end
724724
class HTTP < Protocol
725725

726726
# :stopdoc:
727-
VERSION = "0.7.0"
727+
VERSION = "0.8.0"
728728
HTTPVersion = '1.1'
729729
begin
730730
require 'zlib'
@@ -1179,6 +1179,7 @@ def initialize(address, port = nil) # :nodoc:
11791179
@debug_output = options[:debug_output]
11801180
@response_body_encoding = options[:response_body_encoding]
11811181
@ignore_eof = options[:ignore_eof]
1182+
@tcpsocket_supports_open_timeout = nil
11821183

11831184
@proxy_from_env = false
11841185
@proxy_uri = nil
@@ -1321,6 +1322,9 @@ def response_body_encoding=(value)
13211322
# Sets the proxy password;
13221323
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
13231324
attr_writer :proxy_pass
1325+
1326+
# Sets wheter the proxy uses SSL;
1327+
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
13241328
attr_writer :proxy_use_ssl
13251329

13261330
# Returns the IP address for the connection.
@@ -1632,6 +1636,21 @@ def start # :yield: http
16321636
self
16331637
end
16341638

1639+
# Finishes the \HTTP session:
1640+
#
1641+
# http = Net::HTTP.new(hostname)
1642+
# http.start
1643+
# http.started? # => true
1644+
# http.finish # => nil
1645+
# http.started? # => false
1646+
#
1647+
# Raises IOError if not in a session.
1648+
def finish
1649+
raise IOError, 'HTTP session not yet started' unless started?
1650+
do_finish
1651+
end
1652+
1653+
# :stopdoc:
16351654
def do_start
16361655
connect
16371656
@started = true
@@ -1654,14 +1673,36 @@ def connect
16541673
end
16551674

16561675
debug "opening connection to #{conn_addr}:#{conn_port}..."
1657-
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1658-
begin
1659-
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1660-
rescue => e
1661-
raise e, "Failed to open TCP connection to " +
1662-
"#{conn_addr}:#{conn_port} (#{e.message})"
1663-
end
1664-
}
1676+
begin
1677+
s =
1678+
case @tcpsocket_supports_open_timeout
1679+
when nil, true
1680+
begin
1681+
# Use built-in timeout in TCPSocket.open if available
1682+
sock = TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout)
1683+
@tcpsocket_supports_open_timeout = true
1684+
sock
1685+
rescue ArgumentError => e
1686+
raise if !(e.message.include?('unknown keyword: :open_timeout') || e.message.include?('wrong number of arguments (given 5, expected 2..4)'))
1687+
@tcpsocket_supports_open_timeout = false
1688+
1689+
# Fallback to Timeout.timeout if TCPSocket.open does not support open_timeout
1690+
Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1691+
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1692+
}
1693+
end
1694+
when false
1695+
# The current Ruby is known to not support TCPSocket(open_timeout:).
1696+
# Directly fall back to Timeout.timeout to avoid performance penalty incured by rescue.
1697+
Timeout.timeout(@open_timeout, Net::OpenTimeout) {
1698+
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
1699+
}
1700+
end
1701+
rescue => e
1702+
e = Net::OpenTimeout.new(e) if e.is_a?(Errno::ETIMEDOUT) # for compatibility with previous versions
1703+
raise e, "Failed to open TCP connection to " +
1704+
"#{conn_addr}:#{conn_port} (#{e.message})"
1705+
end
16651706
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
16661707
debug "opened"
16671708
if use_ssl?
@@ -1758,20 +1799,6 @@ def on_connect
17581799
end
17591800
private :on_connect
17601801

1761-
# Finishes the \HTTP session:
1762-
#
1763-
# http = Net::HTTP.new(hostname)
1764-
# http.start
1765-
# http.started? # => true
1766-
# http.finish # => nil
1767-
# http.started? # => false
1768-
#
1769-
# Raises IOError if not in a session.
1770-
def finish
1771-
raise IOError, 'HTTP session not yet started' unless started?
1772-
do_finish
1773-
end
1774-
17751802
def do_finish
17761803
@started = false
17771804
@socket.close if @socket
@@ -1821,6 +1848,8 @@ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_use_ss
18211848
}
18221849
end
18231850

1851+
# :startdoc:
1852+
18241853
class << HTTP
18251854
# Returns true if self is a class which was created by HTTP::Proxy.
18261855
def proxy_class?
@@ -1915,6 +1944,7 @@ def proxy_pass
19151944
alias proxyport proxy_port #:nodoc: obsolete
19161945

19171946
private
1947+
# :stopdoc:
19181948

19191949
def unescape(value)
19201950
require 'cgi/escape'
@@ -1943,6 +1973,7 @@ def edit_path(path)
19431973
path
19441974
end
19451975
end
1976+
# :startdoc:
19461977

19471978
#
19481979
# HTTP operations
@@ -2397,6 +2428,8 @@ def send_entity(path, data, initheader, dest, type, &block)
23972428
res
23982429
end
23992430

2431+
# :stopdoc:
2432+
24002433
IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/ # :nodoc:
24012434

24022435
def transport_request(req)
@@ -2554,7 +2587,7 @@ def debug(msg)
25542587
alias_method :D, :debug
25552588
end
25562589

2557-
# for backward compatibility until Ruby 3.5
2590+
# for backward compatibility until Ruby 4.0
25582591
# https://bugs.ruby-lang.org/issues/20900
25592592
# https://github.com/bblimke/webmock/pull/1081
25602593
HTTPSession = HTTP

lib/net/http/exceptions.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def deconstruct_keys(keys)
3737
end
3838
end
3939

40+
# :stopdoc:
4041
class HTTPError < ProtocolError
4142
include HTTPExceptions
4243
end

lib/net/http/generic_request.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,13 @@ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) # :nodoc:
1919

2020
if URI === uri_or_path then
2121
raise ArgumentError, "not an HTTP URI" unless URI::HTTP === uri_or_path
22-
hostname = uri_or_path.hostname
22+
hostname = uri_or_path.host
2323
raise ArgumentError, "no host component for URI" unless (hostname && hostname.length > 0)
2424
@uri = uri_or_path.dup
25-
host = @uri.hostname.dup
26-
host << ":" << @uri.port.to_s if @uri.port != @uri.default_port
2725
@path = uri_or_path.request_uri
2826
raise ArgumentError, "no HTTP request path given" unless @path
2927
else
3028
@uri = nil
31-
host = nil
3229
raise ArgumentError, "no HTTP request path given" unless uri_or_path
3330
raise ArgumentError, "HTTP request path is empty" if uri_or_path.empty?
3431
@path = uri_or_path.dup
@@ -51,7 +48,7 @@ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) # :nodoc:
5148
initialize_http_header initheader
5249
self['Accept'] ||= '*/*'
5350
self['User-Agent'] ||= 'Ruby'
54-
self['Host'] ||= host if host
51+
self['Host'] ||= @uri.authority if @uri
5552
@body = nil
5653
@body_stream = nil
5754
@body_data = nil
@@ -245,7 +242,7 @@ def update_uri(addr, port, ssl) # :nodoc: internal use only
245242
end
246243

247244
if host = self['host']
248-
host.sub!(/:.*/m, '')
245+
host = URI.parse("//#{host}").host # Remove a port component from the existing Host header
249246
elsif host = @uri.host
250247
else
251248
host = addr
@@ -264,6 +261,8 @@ def update_uri(addr, port, ssl) # :nodoc: internal use only
264261

265262
private
266263

264+
# :stopdoc:
265+
267266
class Chunker #:nodoc:
268267
def initialize(sock)
269268
@sock = sock

lib/net/http/header.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@
179179
# - #each_value: Passes each string field value to the block.
180180
#
181181
module Net::HTTPHeader
182+
# The maximum length of HTTP header keys.
182183
MAX_KEY_LENGTH = 1024
184+
# The maximum length of HTTP header values.
183185
MAX_FIELD_LENGTH = 65536
184186

185187
def initialize_http_header(initheader) #:nodoc:
@@ -267,6 +269,7 @@ def add_field(key, val)
267269
end
268270
end
269271

272+
# :stopdoc:
270273
private def set_field(key, val)
271274
case val
272275
when Enumerable
@@ -294,6 +297,7 @@ def add_field(key, val)
294297
ary.push val
295298
end
296299
end
300+
# :startdoc:
297301

298302
# Returns the array field value for the given +key+,
299303
# or +nil+ if there is no such field;
@@ -490,7 +494,7 @@ def each_capitalized
490494

491495
alias canonical_each each_capitalized
492496

493-
def capitalize(name)
497+
def capitalize(name) # :nodoc:
494498
name.to_s.split('-'.freeze).map {|s| s.capitalize }.join('-'.freeze)
495499
end
496500
private :capitalize
@@ -957,20 +961,20 @@ def proxy_basic_auth(account, password)
957961
@header['proxy-authorization'] = [basic_encode(account, password)]
958962
end
959963

960-
def basic_encode(account, password)
964+
def basic_encode(account, password) # :nodoc:
961965
'Basic ' + ["#{account}:#{password}"].pack('m0')
962966
end
963967
private :basic_encode
964968

965-
# Returns whether the HTTP session is to be closed.
969+
# Returns whether the HTTP session is to be closed.
966970
def connection_close?
967971
token = /(?:\A|,)\s*close\s*(?:\z|,)/i
968972
@header['connection']&.grep(token) {return true}
969973
@header['proxy-connection']&.grep(token) {return true}
970974
false
971975
end
972976

973-
# Returns whether the HTTP session is to be kept alive.
977+
# Returns whether the HTTP session is to be kept alive.
974978
def connection_keep_alive?
975979
token = /(?:\A|,)\s*keep-alive\s*(?:\z|,)/i
976980
@header['connection']&.grep(token) {return true}

0 commit comments

Comments
 (0)