net-http 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/test.yml +3 -5
- data/Gemfile +1 -0
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/lib/net/http/backward.rb +26 -12
- data/lib/net/http/exceptions.rb +27 -26
- data/lib/net/http/generic_request.rb +6 -7
- data/lib/net/http/header.rb +3 -2
- data/lib/net/http/response.rb +176 -1
- data/lib/net/http/responses.rb +228 -223
- data/lib/net/http.rb +96 -39
- data/net-http.gemspec +0 -2
- metadata +4 -18
- data/Gemfile.lock +0 -23
data/lib/net/http.rb
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
|
23
23
|
require 'net/protocol'
|
24
24
|
require 'uri'
|
25
|
+
require 'resolv'
|
25
26
|
autoload :OpenSSL, 'openssl'
|
26
27
|
|
27
28
|
module Net #:nodoc:
|
@@ -132,7 +133,7 @@ module Net #:nodoc:
|
|
132
133
|
# puts res.class.name # => 'HTTPOK'
|
133
134
|
#
|
134
135
|
# # Body
|
135
|
-
# puts res.body
|
136
|
+
# puts res.body
|
136
137
|
#
|
137
138
|
# === Following Redirection
|
138
139
|
#
|
@@ -327,6 +328,8 @@ module Net #:nodoc:
|
|
327
328
|
# HTTPInformation:: 1xx
|
328
329
|
# HTTPContinue:: 100
|
329
330
|
# HTTPSwitchProtocol:: 101
|
331
|
+
# HTTPProcessing:: 102
|
332
|
+
# HTTPEarlyHints:: 103
|
330
333
|
# HTTPSuccess:: 2xx
|
331
334
|
# HTTPOK:: 200
|
332
335
|
# HTTPCreated:: 201
|
@@ -336,6 +339,7 @@ module Net #:nodoc:
|
|
336
339
|
# HTTPResetContent:: 205
|
337
340
|
# HTTPPartialContent:: 206
|
338
341
|
# HTTPMultiStatus:: 207
|
342
|
+
# HTTPAlreadyReported:: 208
|
339
343
|
# HTTPIMUsed:: 226
|
340
344
|
# HTTPRedirection:: 3xx
|
341
345
|
# HTTPMultipleChoices:: 300
|
@@ -345,6 +349,7 @@ module Net #:nodoc:
|
|
345
349
|
# HTTPNotModified:: 304
|
346
350
|
# HTTPUseProxy:: 305
|
347
351
|
# HTTPTemporaryRedirect:: 307
|
352
|
+
# HTTPPermanentRedirect:: 308
|
348
353
|
# HTTPClientError:: 4xx
|
349
354
|
# HTTPBadRequest:: 400
|
350
355
|
# HTTPUnauthorized:: 401
|
@@ -364,6 +369,7 @@ module Net #:nodoc:
|
|
364
369
|
# HTTPUnsupportedMediaType:: 415
|
365
370
|
# HTTPRequestedRangeNotSatisfiable:: 416
|
366
371
|
# HTTPExpectationFailed:: 417
|
372
|
+
# HTTPMisdirectedRequest:: 421
|
367
373
|
# HTTPUnprocessableEntity:: 422
|
368
374
|
# HTTPLocked:: 423
|
369
375
|
# HTTPFailedDependency:: 424
|
@@ -379,7 +385,10 @@ module Net #:nodoc:
|
|
379
385
|
# HTTPServiceUnavailable:: 503
|
380
386
|
# HTTPGatewayTimeOut:: 504
|
381
387
|
# HTTPVersionNotSupported:: 505
|
388
|
+
# HTTPVariantAlsoNegotiates:: 506
|
382
389
|
# HTTPInsufficientStorage:: 507
|
390
|
+
# HTTPLoopDetected:: 508
|
391
|
+
# HTTPNotExtended:: 510
|
383
392
|
# HTTPNetworkAuthenticationRequired:: 511
|
384
393
|
#
|
385
394
|
# There is also the Net::HTTPBadResponse exception which is raised when
|
@@ -388,12 +397,11 @@ module Net #:nodoc:
|
|
388
397
|
class HTTP < Protocol
|
389
398
|
|
390
399
|
# :stopdoc:
|
391
|
-
VERSION = "0.
|
400
|
+
VERSION = "0.3.0"
|
392
401
|
Revision = %q$Revision$.split[1]
|
393
402
|
HTTPVersion = '1.1'
|
394
403
|
begin
|
395
404
|
require 'zlib'
|
396
|
-
require 'stringio' #for our purposes (unpacking gzip) lump these together
|
397
405
|
HAVE_ZLIB=true
|
398
406
|
rescue LoadError
|
399
407
|
HAVE_ZLIB=false
|
@@ -524,14 +532,13 @@ module Net #:nodoc:
|
|
524
532
|
#
|
525
533
|
# { "cmd" => "search", "q" => "ruby", "max" => "50" }
|
526
534
|
#
|
527
|
-
# This method also does Basic Authentication
|
535
|
+
# This method also does Basic Authentication if and only if +url+.user exists.
|
528
536
|
# But userinfo for authentication is deprecated (RFC3986).
|
529
537
|
# So this feature will be removed.
|
530
538
|
#
|
531
539
|
# Example:
|
532
540
|
#
|
533
541
|
# require 'net/http'
|
534
|
-
# require 'uri'
|
535
542
|
#
|
536
543
|
# Net::HTTP.post_form URI('http://www.example.com/search.cgi'),
|
537
544
|
# { "q" => "ruby", "max" => "50" }
|
@@ -691,6 +698,8 @@ module Net #:nodoc:
|
|
691
698
|
@continue_timeout = nil
|
692
699
|
@max_retries = 1
|
693
700
|
@debug_output = nil
|
701
|
+
@response_body_encoding = false
|
702
|
+
@ignore_eof = true
|
694
703
|
|
695
704
|
@proxy_from_env = false
|
696
705
|
@proxy_uri = nil
|
@@ -738,6 +747,18 @@ module Net #:nodoc:
|
|
738
747
|
# The local port used to establish the connection.
|
739
748
|
attr_accessor :local_port
|
740
749
|
|
750
|
+
# The encoding to use for the response body. If Encoding, uses the
|
751
|
+
# specified encoding. If other true value, tries to detect the response
|
752
|
+
# body encoding.
|
753
|
+
attr_reader :response_body_encoding
|
754
|
+
|
755
|
+
# Set the encoding to use for the response body. If given a String, find
|
756
|
+
# the related Encoding.
|
757
|
+
def response_body_encoding=(value)
|
758
|
+
value = Encoding.find(value) if value.is_a?(String)
|
759
|
+
@response_body_encoding = value
|
760
|
+
end
|
761
|
+
|
741
762
|
attr_writer :proxy_from_env
|
742
763
|
attr_writer :proxy_address
|
743
764
|
attr_writer :proxy_port
|
@@ -819,6 +840,10 @@ module Net #:nodoc:
|
|
819
840
|
# The default value is 2 seconds.
|
820
841
|
attr_accessor :keep_alive_timeout
|
821
842
|
|
843
|
+
# Whether to ignore EOF when reading response bodies with defined
|
844
|
+
# Content-Length headers. For backwards compatibility, the default is true.
|
845
|
+
attr_accessor :ignore_eof
|
846
|
+
|
822
847
|
# Returns true if the HTTP session has been started.
|
823
848
|
def started?
|
824
849
|
@started
|
@@ -973,6 +998,12 @@ module Net #:nodoc:
|
|
973
998
|
private :do_start
|
974
999
|
|
975
1000
|
def connect
|
1001
|
+
if use_ssl?
|
1002
|
+
# reference early to load OpenSSL before connecting,
|
1003
|
+
# as OpenSSL may take time to load.
|
1004
|
+
@ssl_context = OpenSSL::SSL::SSLContext.new
|
1005
|
+
end
|
1006
|
+
|
976
1007
|
if proxy? then
|
977
1008
|
conn_addr = proxy_address
|
978
1009
|
conn_port = proxy_port
|
@@ -981,7 +1012,7 @@ module Net #:nodoc:
|
|
981
1012
|
conn_port = port
|
982
1013
|
end
|
983
1014
|
|
984
|
-
|
1015
|
+
debug "opening connection to #{conn_addr}:#{conn_port}..."
|
985
1016
|
s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
|
986
1017
|
begin
|
987
1018
|
TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
|
@@ -991,7 +1022,7 @@ module Net #:nodoc:
|
|
991
1022
|
end
|
992
1023
|
}
|
993
1024
|
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
994
|
-
|
1025
|
+
debug "opened"
|
995
1026
|
if use_ssl?
|
996
1027
|
if proxy?
|
997
1028
|
plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
|
@@ -1020,35 +1051,56 @@ module Net #:nodoc:
|
|
1020
1051
|
end
|
1021
1052
|
end
|
1022
1053
|
end
|
1023
|
-
@ssl_context = OpenSSL::SSL::SSLContext.new
|
1024
1054
|
@ssl_context.set_params(ssl_parameters)
|
1025
|
-
@ssl_context.session_cache_mode
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1055
|
+
unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
|
1056
|
+
@ssl_context.session_cache_mode =
|
1057
|
+
OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
|
1058
|
+
OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
|
1059
|
+
end
|
1060
|
+
if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
|
1061
|
+
@ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
# Still do the post_connection_check below even if connecting
|
1065
|
+
# to IP address
|
1066
|
+
verify_hostname = @ssl_context.verify_hostname
|
1067
|
+
|
1068
|
+
# Server Name Indication (SNI) RFC 3546/6066
|
1069
|
+
case @address
|
1070
|
+
when Resolv::IPv4::Regex, Resolv::IPv6::Regex
|
1071
|
+
# don't set SNI, as IP addresses in SNI is not valid
|
1072
|
+
# per RFC 6066, section 3.
|
1073
|
+
|
1074
|
+
# Avoid openssl warning
|
1075
|
+
@ssl_context.verify_hostname = false
|
1076
|
+
else
|
1077
|
+
ssl_host_address = @address
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
debug "starting SSL for #{conn_addr}:#{conn_port}..."
|
1030
1081
|
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
|
1031
1082
|
s.sync_close = true
|
1032
|
-
|
1033
|
-
|
1083
|
+
s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
|
1084
|
+
|
1034
1085
|
if @ssl_session and
|
1035
1086
|
Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
|
1036
1087
|
s.session = @ssl_session
|
1037
1088
|
end
|
1038
1089
|
ssl_socket_connect(s, @open_timeout)
|
1039
|
-
if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) &&
|
1090
|
+
if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
|
1040
1091
|
s.post_connection_check(@address)
|
1041
1092
|
end
|
1042
|
-
|
1093
|
+
debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
|
1043
1094
|
end
|
1044
1095
|
@socket = BufferedIO.new(s, read_timeout: @read_timeout,
|
1045
1096
|
write_timeout: @write_timeout,
|
1046
1097
|
continue_timeout: @continue_timeout,
|
1047
1098
|
debug_output: @debug_output)
|
1099
|
+
@last_communicated = nil
|
1048
1100
|
on_connect
|
1049
1101
|
rescue => exception
|
1050
1102
|
if s
|
1051
|
-
|
1103
|
+
debug "Conn close because of connect error #{exception}"
|
1052
1104
|
s.close
|
1053
1105
|
end
|
1054
1106
|
raise
|
@@ -1170,17 +1222,11 @@ module Net #:nodoc:
|
|
1170
1222
|
end
|
1171
1223
|
end
|
1172
1224
|
|
1173
|
-
# [Bug #12921]
|
1174
|
-
if /linux|freebsd|darwin/ =~ RUBY_PLATFORM
|
1175
|
-
ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = true
|
1176
|
-
else
|
1177
|
-
ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE = false
|
1178
|
-
end
|
1179
|
-
|
1180
1225
|
# The username of the proxy server, if one is configured.
|
1181
1226
|
def proxy_user
|
1182
|
-
if
|
1183
|
-
proxy_uri&.user
|
1227
|
+
if @proxy_from_env
|
1228
|
+
user = proxy_uri&.user
|
1229
|
+
unescape(user) if user
|
1184
1230
|
else
|
1185
1231
|
@proxy_user
|
1186
1232
|
end
|
@@ -1188,8 +1234,9 @@ module Net #:nodoc:
|
|
1188
1234
|
|
1189
1235
|
# The password of the proxy server, if one is configured.
|
1190
1236
|
def proxy_pass
|
1191
|
-
if
|
1192
|
-
proxy_uri&.password
|
1237
|
+
if @proxy_from_env
|
1238
|
+
pass = proxy_uri&.password
|
1239
|
+
unescape(pass) if pass
|
1193
1240
|
else
|
1194
1241
|
@proxy_pass
|
1195
1242
|
end
|
@@ -1200,6 +1247,11 @@ module Net #:nodoc:
|
|
1200
1247
|
|
1201
1248
|
private
|
1202
1249
|
|
1250
|
+
def unescape(value)
|
1251
|
+
require 'cgi/util'
|
1252
|
+
CGI.unescape(value)
|
1253
|
+
end
|
1254
|
+
|
1203
1255
|
# without proxy, obsolete
|
1204
1256
|
|
1205
1257
|
def conn_address # :nodoc:
|
@@ -1556,6 +1608,8 @@ module Net #:nodoc:
|
|
1556
1608
|
begin
|
1557
1609
|
res = HTTPResponse.read_new(@socket)
|
1558
1610
|
res.decode_content = req.decode_content
|
1611
|
+
res.body_encoding = @response_body_encoding
|
1612
|
+
res.ignore_eof = @ignore_eof
|
1559
1613
|
end while res.kind_of?(HTTPInformation)
|
1560
1614
|
|
1561
1615
|
res.uri = req.uri
|
@@ -1575,10 +1629,10 @@ module Net #:nodoc:
|
|
1575
1629
|
if count < max_retries && IDEMPOTENT_METHODS_.include?(req.method)
|
1576
1630
|
count += 1
|
1577
1631
|
@socket.close if @socket
|
1578
|
-
|
1632
|
+
debug "Conn close because of error #{exception}, and retry"
|
1579
1633
|
retry
|
1580
1634
|
end
|
1581
|
-
|
1635
|
+
debug "Conn close because of error #{exception}"
|
1582
1636
|
@socket.close if @socket
|
1583
1637
|
raise
|
1584
1638
|
end
|
@@ -1586,7 +1640,7 @@ module Net #:nodoc:
|
|
1586
1640
|
end_transport req, res
|
1587
1641
|
res
|
1588
1642
|
rescue => exception
|
1589
|
-
|
1643
|
+
debug "Conn close because of error #{exception}"
|
1590
1644
|
@socket.close if @socket
|
1591
1645
|
raise exception
|
1592
1646
|
end
|
@@ -1596,11 +1650,11 @@ module Net #:nodoc:
|
|
1596
1650
|
connect
|
1597
1651
|
elsif @last_communicated
|
1598
1652
|
if @last_communicated + @keep_alive_timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
1599
|
-
|
1653
|
+
debug 'Conn close because of keep_alive_timeout'
|
1600
1654
|
@socket.close
|
1601
1655
|
connect
|
1602
1656
|
elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
|
1603
|
-
|
1657
|
+
debug "Conn close because of EOF"
|
1604
1658
|
@socket.close
|
1605
1659
|
connect
|
1606
1660
|
end
|
@@ -1618,15 +1672,15 @@ module Net #:nodoc:
|
|
1618
1672
|
@curr_http_version = res.http_version
|
1619
1673
|
@last_communicated = nil
|
1620
1674
|
if @socket.closed?
|
1621
|
-
|
1675
|
+
debug 'Conn socket closed'
|
1622
1676
|
elsif not res.body and @close_on_empty_response
|
1623
|
-
|
1677
|
+
debug 'Conn close'
|
1624
1678
|
@socket.close
|
1625
1679
|
elsif keep_alive?(req, res)
|
1626
|
-
|
1680
|
+
debug 'Conn keep-alive'
|
1627
1681
|
@last_communicated = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
1628
1682
|
else
|
1629
|
-
|
1683
|
+
debug 'Conn close'
|
1630
1684
|
@socket.close
|
1631
1685
|
end
|
1632
1686
|
end
|
@@ -1681,11 +1735,14 @@ module Net #:nodoc:
|
|
1681
1735
|
default_port == port ? addr : "#{addr}:#{port}"
|
1682
1736
|
end
|
1683
1737
|
|
1684
|
-
|
1738
|
+
# Adds a message to debugging output
|
1739
|
+
def debug(msg)
|
1685
1740
|
return unless @debug_output
|
1686
1741
|
@debug_output << msg
|
1687
1742
|
@debug_output << "\n"
|
1688
1743
|
end
|
1744
|
+
|
1745
|
+
alias_method :D, :debug
|
1689
1746
|
end
|
1690
1747
|
|
1691
1748
|
end
|
data/net-http.gemspec
CHANGED
@@ -28,9 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
`git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
29
29
|
end
|
30
30
|
spec.bindir = "exe"
|
31
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
31
|
spec.require_paths = ["lib"]
|
33
32
|
|
34
|
-
spec.add_dependency "net-protocol"
|
35
33
|
spec.add_dependency "uri"
|
36
34
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: net-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- NARUSE, Yui
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-10-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: net-protocol
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: uri
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,10 +31,10 @@ executables: []
|
|
45
31
|
extensions: []
|
46
32
|
extra_rdoc_files: []
|
47
33
|
files:
|
34
|
+
- ".github/dependabot.yml"
|
48
35
|
- ".github/workflows/test.yml"
|
49
36
|
- ".gitignore"
|
50
37
|
- Gemfile
|
51
|
-
- Gemfile.lock
|
52
38
|
- LICENSE.txt
|
53
39
|
- README.md
|
54
40
|
- Rakefile
|
@@ -89,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
75
|
- !ruby/object:Gem::Version
|
90
76
|
version: '0'
|
91
77
|
requirements: []
|
92
|
-
rubygems_version: 3.
|
78
|
+
rubygems_version: 3.4.0.dev
|
93
79
|
signing_key:
|
94
80
|
specification_version: 4
|
95
81
|
summary: HTTP client api for Ruby.
|
data/Gemfile.lock
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
net-http (0.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
power_assert (1.1.5)
|
10
|
-
rake (13.0.1)
|
11
|
-
test-unit (3.3.5)
|
12
|
-
power_assert
|
13
|
-
|
14
|
-
PLATFORMS
|
15
|
-
ruby
|
16
|
-
|
17
|
-
DEPENDENCIES
|
18
|
-
net-http!
|
19
|
-
rake
|
20
|
-
test-unit
|
21
|
-
|
22
|
-
BUNDLED WITH
|
23
|
-
2.1.4
|