net-http 0.1.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a306a97039eef1800016a611dee36fa0d342b5f234bf6e0a512d981abd12ce8d
4
- data.tar.gz: 39583accf1ec3b888c4e368eb0d3cf41add46ebfd18a6d7dcbea1cc69712f219
3
+ metadata.gz: ee3df6b6afad0f163708cc0fc0f0a16f4a3b394b56c3c389c55a55274f38c3e7
4
+ data.tar.gz: 17a0329a4c031e923cd597af5abcd31d08a853ffbb9d9a58308f6bb44b02b88d
5
5
  SHA512:
6
- metadata.gz: 21ab016c4d12100c405aec7b8426d81f4a88ac2bc7019353d729837d17e3a95899df04818f787319c32f29b349b7527b7903a65a897e8353382d5461070465c7
7
- data.tar.gz: 38593be710550d52aaf31d50d746e7f5da92fb1c3d4b451968bda3c0af9b033acefc2fd404f6a083025d340d8abebd7d2061fa77343f081b78bd48c19aa82b39
6
+ metadata.gz: 27b412cb8ea24d0a24bc5f3a835cef426481ca6f921323629b0bbabf0b9752373c5f6904179984068fd8a1e7c666f29c989636baa43989a835259252a0278eef
7
+ data.tar.gz: 52772055904e6f294fb72a13d270b269b37dc3b588c91afe517e3ea74fb639aac6b6586092cb1fa1de65eb9c518290e79ddde3b6804e65b5b532233d295e0d38
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
@@ -7,18 +7,16 @@ jobs:
7
7
  name: build (${{ matrix.ruby }} / ${{ matrix.os }})
8
8
  strategy:
9
9
  matrix:
10
- ruby: [ 2.7, 2.6, head ]
10
+ ruby: [ 3.1, '3.0', 2.7, 2.6, head ]
11
11
  os: [ ubuntu-latest, macos-latest ]
12
12
  runs-on: ${{ matrix.os }}
13
13
  steps:
14
- - uses: actions/checkout@master
14
+ - uses: actions/checkout@v3
15
15
  - name: Set up Ruby
16
16
  uses: ruby/setup-ruby@v1
17
17
  with:
18
18
  ruby-version: ${{ matrix.ruby }}
19
19
  - name: Install dependencies
20
- run: |
21
- gem install bundler --no-document
22
- bundle install
20
+ run: bundle install
23
21
  - name: Run test
24
22
  run: rake test
data/Gemfile CHANGED
@@ -4,3 +4,4 @@ gemspec
4
4
 
5
5
  gem "rake"
6
6
  gem "test-unit"
7
+ gem "webrick"
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Net::Http
1
+ # Net::HTTP
2
2
 
3
3
  Net::HTTP provides a rich library which can be used to build HTTP
4
4
  user-agents. For more details about HTTP see
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ end
9
9
 
10
10
  task :sync_tool do
11
11
  require 'fileutils'
12
- FileUtils.cp "../ruby/tool/lib/test/unit/core_assertions.rb", "./test/lib"
12
+ FileUtils.cp "../ruby/tool/lib/core_assertions.rb", "./test/lib"
13
13
  FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
14
14
  FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
15
15
  end
@@ -5,22 +5,36 @@
5
5
 
6
6
  class Net::HTTP
7
7
  ProxyMod = ProxyDelta
8
- end
9
-
10
- module Net
11
- HTTPSession = Net::HTTP
8
+ deprecate_constant :ProxyMod
12
9
  end
13
10
 
14
11
  module Net::NetPrivate
15
12
  HTTPRequest = ::Net::HTTPRequest
13
+ deprecate_constant :HTTPRequest
16
14
  end
17
15
 
18
- Net::HTTPInformationCode = Net::HTTPInformation
19
- Net::HTTPSuccessCode = Net::HTTPSuccess
20
- Net::HTTPRedirectionCode = Net::HTTPRedirection
21
- Net::HTTPRetriableCode = Net::HTTPRedirection
22
- Net::HTTPClientErrorCode = Net::HTTPClientError
23
- Net::HTTPFatalErrorCode = Net::HTTPClientError
24
- Net::HTTPServerErrorCode = Net::HTTPServerError
25
- Net::HTTPResponceReceiver = Net::HTTPResponse
16
+ module Net
17
+ HTTPSession = HTTP
26
18
 
19
+ HTTPInformationCode = HTTPInformation
20
+ HTTPSuccessCode = HTTPSuccess
21
+ HTTPRedirectionCode = HTTPRedirection
22
+ HTTPRetriableCode = HTTPRedirection
23
+ HTTPClientErrorCode = HTTPClientError
24
+ HTTPFatalErrorCode = HTTPClientError
25
+ HTTPServerErrorCode = HTTPServerError
26
+ HTTPResponseReceiver = HTTPResponse
27
+
28
+ HTTPResponceReceiver = HTTPResponse # Typo since 2001
29
+
30
+ deprecate_constant :HTTPSession,
31
+ :HTTPInformationCode,
32
+ :HTTPSuccessCode,
33
+ :HTTPRedirectionCode,
34
+ :HTTPRetriableCode,
35
+ :HTTPClientErrorCode,
36
+ :HTTPFatalErrorCode,
37
+ :HTTPServerErrorCode,
38
+ :HTTPResponseReceiver,
39
+ :HTTPResponceReceiver
40
+ end
@@ -31,12 +31,12 @@ class Net::HTTPGenericRequest
31
31
 
32
32
  @decode_content = false
33
33
 
34
- if @response_has_body and Net::HTTP::HAVE_ZLIB then
34
+ if Net::HTTP::HAVE_ZLIB then
35
35
  if !initheader ||
36
36
  !initheader.keys.any? { |k|
37
37
  %w[accept-encoding range].include? k.downcase
38
38
  } then
39
- @decode_content = true
39
+ @decode_content = true if @response_has_body
40
40
  initheader = initheader ? initheader.dup : {}
41
41
  initheader["accept-encoding"] =
42
42
  "gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
@@ -143,7 +143,7 @@ class Net::HTTPGenericRequest
143
143
  end
144
144
 
145
145
  if host = self['host']
146
- host.sub!(/:.*/s, ''.freeze)
146
+ host.sub!(/:.*/m, ''.freeze)
147
147
  elsif host = @uri.host
148
148
  else
149
149
  host = addr
@@ -202,9 +202,7 @@ class Net::HTTPGenericRequest
202
202
  IO.copy_stream(f, chunker)
203
203
  chunker.finish
204
204
  else
205
- # copy_stream can sendfile() to sock.io unless we use SSL.
206
- # If sock.io is an SSLSocket, copy_stream will hit SSL_write()
207
- IO.copy_stream(f, sock.io)
205
+ IO.copy_stream(f, sock)
208
206
  end
209
207
  end
210
208
 
@@ -84,6 +84,8 @@ class Net::HTTPResponse
84
84
  @read = false
85
85
  @uri = nil
86
86
  @decode_content = false
87
+ @body_encoding = false
88
+ @ignore_eof = true
87
89
  end
88
90
 
89
91
  # The HTTP version supported by the server.
@@ -106,6 +108,22 @@ class Net::HTTPResponse
106
108
  # Accept-Encoding header from the user.
107
109
  attr_accessor :decode_content
108
110
 
111
+ # The encoding to use for the response body. If Encoding, use that encoding.
112
+ # If other true value, attempt to detect the appropriate encoding, and use
113
+ # that.
114
+ attr_reader :body_encoding
115
+
116
+ # Set the encoding to use for the response body. If given a String, find
117
+ # the related Encoding.
118
+ def body_encoding=(value)
119
+ value = Encoding.find(value) if value.is_a?(String)
120
+ @body_encoding = value
121
+ end
122
+
123
+ # Whether to ignore EOF when reading bodies with a specified Content-Length
124
+ # header.
125
+ attr_accessor :ignore_eof
126
+
109
127
  def inspect
110
128
  "#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
111
129
  end
@@ -214,6 +232,17 @@ class Net::HTTPResponse
214
232
  end
215
233
  @read = true
216
234
 
235
+ case enc = @body_encoding
236
+ when Encoding, false, nil
237
+ # Encoding: force given encoding
238
+ # false/nil: do not force encoding
239
+ else
240
+ # other value: detect encoding from body
241
+ enc = detect_encoding(@body)
242
+ end
243
+
244
+ @body.force_encoding(enc) if enc
245
+
217
246
  @body
218
247
  end
219
248
 
@@ -245,6 +274,141 @@ class Net::HTTPResponse
245
274
 
246
275
  private
247
276
 
277
+ # :nodoc:
278
+ def detect_encoding(str, encoding=nil)
279
+ if encoding
280
+ elsif encoding = type_params['charset']
281
+ elsif encoding = check_bom(str)
282
+ else
283
+ encoding = case content_type&.downcase
284
+ when %r{text/x(?:ht)?ml|application/(?:[^+]+\+)?xml}
285
+ /\A<xml[ \t\r\n]+
286
+ version[ \t\r\n]*=[ \t\r\n]*(?:"[0-9.]+"|'[0-9.]*')[ \t\r\n]+
287
+ encoding[ \t\r\n]*=[ \t\r\n]*
288
+ (?:"([A-Za-z][\-A-Za-z0-9._]*)"|'([A-Za-z][\-A-Za-z0-9._]*)')/x =~ str
289
+ encoding = $1 || $2 || Encoding::UTF_8
290
+ when %r{text/html.*}
291
+ sniff_encoding(str)
292
+ end
293
+ end
294
+ return encoding
295
+ end
296
+
297
+ # :nodoc:
298
+ def sniff_encoding(str, encoding=nil)
299
+ # the encoding sniffing algorithm
300
+ # http://www.w3.org/TR/html5/parsing.html#determining-the-character-encoding
301
+ if enc = scanning_meta(str)
302
+ enc
303
+ # 6. last visited page or something
304
+ # 7. frequency
305
+ elsif str.ascii_only?
306
+ Encoding::US_ASCII
307
+ elsif str.dup.force_encoding(Encoding::UTF_8).valid_encoding?
308
+ Encoding::UTF_8
309
+ end
310
+ # 8. implementation-defined or user-specified
311
+ end
312
+
313
+ # :nodoc:
314
+ def check_bom(str)
315
+ case str.byteslice(0, 2)
316
+ when "\xFE\xFF"
317
+ return Encoding::UTF_16BE
318
+ when "\xFF\xFE"
319
+ return Encoding::UTF_16LE
320
+ end
321
+ if "\xEF\xBB\xBF" == str.byteslice(0, 3)
322
+ return Encoding::UTF_8
323
+ end
324
+ nil
325
+ end
326
+
327
+ # :nodoc:
328
+ def scanning_meta(str)
329
+ require 'strscan'
330
+ ss = StringScanner.new(str)
331
+ if ss.scan_until(/<meta[\t\n\f\r ]*/)
332
+ attrs = {} # attribute_list
333
+ got_pragma = false
334
+ need_pragma = nil
335
+ charset = nil
336
+
337
+ # step: Attributes
338
+ while attr = get_attribute(ss)
339
+ name, value = *attr
340
+ next if attrs[name]
341
+ attrs[name] = true
342
+ case name
343
+ when 'http-equiv'
344
+ got_pragma = true if value == 'content-type'
345
+ when 'content'
346
+ encoding = extracting_encodings_from_meta_elements(value)
347
+ unless charset
348
+ charset = encoding
349
+ end
350
+ need_pragma = true
351
+ when 'charset'
352
+ need_pragma = false
353
+ charset = value
354
+ end
355
+ end
356
+
357
+ # step: Processing
358
+ return if need_pragma.nil?
359
+ return if need_pragma && !got_pragma
360
+
361
+ charset = Encoding.find(charset) rescue nil
362
+ return unless charset
363
+ charset = Encoding::UTF_8 if charset == Encoding::UTF_16
364
+ return charset # tentative
365
+ end
366
+ nil
367
+ end
368
+
369
+ def get_attribute(ss)
370
+ ss.scan(/[\t\n\f\r \/]*/)
371
+ if ss.peek(1) == '>'
372
+ ss.getch
373
+ return nil
374
+ end
375
+ name = ss.scan(/[^=\t\n\f\r \/>]*/)
376
+ name.downcase!
377
+ raise if name.empty?
378
+ ss.skip(/[\t\n\f\r ]*/)
379
+ if ss.getch != '='
380
+ value = ''
381
+ return [name, value]
382
+ end
383
+ ss.skip(/[\t\n\f\r ]*/)
384
+ case ss.peek(1)
385
+ when '"'
386
+ ss.getch
387
+ value = ss.scan(/[^"]+/)
388
+ value.downcase!
389
+ ss.getch
390
+ when "'"
391
+ ss.getch
392
+ value = ss.scan(/[^']+/)
393
+ value.downcase!
394
+ ss.getch
395
+ when '>'
396
+ value = ''
397
+ else
398
+ value = ss.scan(/[^\t\n\f\r >]+/)
399
+ value.downcase!
400
+ end
401
+ [name, value]
402
+ end
403
+
404
+ def extracting_encodings_from_meta_elements(value)
405
+ # http://dev.w3.org/html5/spec/fetching-resources.html#algorithm-for-extracting-an-encoding-from-a-meta-element
406
+ if /charset[\t\n\f\r ]*=(?:"([^"]*)"|'([^']*)'|["']|\z|([^\t\n\f\r ;]+))/i =~ value
407
+ return $1 || $2 || $3
408
+ end
409
+ return nil
410
+ end
411
+
248
412
  ##
249
413
  # Checks for a supported Content-Encoding header and yields an Inflate
250
414
  # wrapper for this response's socket when zlib is present. If the
@@ -272,6 +436,9 @@ class Net::HTTPResponse
272
436
  ensure
273
437
  begin
274
438
  inflate_body_io.finish
439
+ if self['content-length']
440
+ self['content-length'] = inflate_body_io.bytes_inflated.to_s
441
+ end
275
442
  rescue => err
276
443
  # Ignore #finish's error if there is an exception from yield
277
444
  raise err if success
@@ -297,7 +464,7 @@ class Net::HTTPResponse
297
464
 
298
465
  clen = content_length()
299
466
  if clen
300
- @socket.read clen, dest, true # ignore EOF
467
+ @socket.read clen, dest, @ignore_eof
301
468
  return
302
469
  end
303
470
  clen = range_length()
@@ -373,6 +540,14 @@ class Net::HTTPResponse
373
540
  @inflate.finish
374
541
  end
375
542
 
543
+ ##
544
+ # The number of bytes inflated, used to update the Content-Length of
545
+ # the response.
546
+
547
+ def bytes_inflated
548
+ @inflate.total_out
549
+ end
550
+
376
551
  ##
377
552
  # Returns a Net::ReadAdapter that inflates each read chunk into +dest+.
378
553
  #
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:
@@ -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.1.1"
400
+ VERSION = "0.2.2"
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 iff +url+.user exists.
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,17 +1012,16 @@ module Net #:nodoc:
981
1012
  conn_port = port
982
1013
  end
983
1014
 
984
- D "opening connection to #{conn_addr}:#{conn_port}..."
985
- s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
986
- begin
987
- TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
988
- rescue => e
989
- raise e, "Failed to open TCP connection to " +
990
- "#{conn_addr}:#{conn_port} (#{e.message})"
991
- end
992
- }
1015
+ debug "opening connection to #{conn_addr}:#{conn_port}..."
1016
+ begin
1017
+ s = Socket.tcp conn_addr, conn_port, @local_host, @local_port, connect_timeout: @open_timeout
1018
+ rescue => e
1019
+ e = Net::OpenTimeout.new(e) if e.is_a?(Errno::ETIMEDOUT) #for compatibility with previous versions
1020
+ raise e, "Failed to open TCP connection to " +
1021
+ "#{conn_addr}:#{conn_port} (#{e.message})"
1022
+ end
993
1023
  s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
994
- D "opened"
1024
+ debug "opened"
995
1025
  if use_ssl?
996
1026
  if proxy?
997
1027
  plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
@@ -1020,35 +1050,56 @@ module Net #:nodoc:
1020
1050
  end
1021
1051
  end
1022
1052
  end
1023
- @ssl_context = OpenSSL::SSL::SSLContext.new
1024
1053
  @ssl_context.set_params(ssl_parameters)
1025
- @ssl_context.session_cache_mode =
1026
- OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
1027
- OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
1028
- @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
1029
- D "starting SSL for #{conn_addr}:#{conn_port}..."
1054
+ unless @ssl_context.session_cache_mode.nil? # a dummy method on JRuby
1055
+ @ssl_context.session_cache_mode =
1056
+ OpenSSL::SSL::SSLContext::SESSION_CACHE_CLIENT |
1057
+ OpenSSL::SSL::SSLContext::SESSION_CACHE_NO_INTERNAL_STORE
1058
+ end
1059
+ if @ssl_context.respond_to?(:session_new_cb) # not implemented under JRuby
1060
+ @ssl_context.session_new_cb = proc {|sock, sess| @ssl_session = sess }
1061
+ end
1062
+
1063
+ # Still do the post_connection_check below even if connecting
1064
+ # to IP address
1065
+ verify_hostname = @ssl_context.verify_hostname
1066
+
1067
+ # Server Name Indication (SNI) RFC 3546/6066
1068
+ case @address
1069
+ when Resolv::IPv4::Regex, Resolv::IPv6::Regex
1070
+ # don't set SNI, as IP addresses in SNI is not valid
1071
+ # per RFC 6066, section 3.
1072
+
1073
+ # Avoid openssl warning
1074
+ @ssl_context.verify_hostname = false
1075
+ else
1076
+ ssl_host_address = @address
1077
+ end
1078
+
1079
+ debug "starting SSL for #{conn_addr}:#{conn_port}..."
1030
1080
  s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
1031
1081
  s.sync_close = true
1032
- # Server Name Indication (SNI) RFC 3546
1033
- s.hostname = @address if s.respond_to? :hostname=
1082
+ s.hostname = ssl_host_address if s.respond_to?(:hostname=) && ssl_host_address
1083
+
1034
1084
  if @ssl_session and
1035
1085
  Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
1036
1086
  s.session = @ssl_session
1037
1087
  end
1038
1088
  ssl_socket_connect(s, @open_timeout)
1039
- if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname
1089
+ if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && verify_hostname
1040
1090
  s.post_connection_check(@address)
1041
1091
  end
1042
- D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
1092
+ debug "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
1043
1093
  end
1044
1094
  @socket = BufferedIO.new(s, read_timeout: @read_timeout,
1045
1095
  write_timeout: @write_timeout,
1046
1096
  continue_timeout: @continue_timeout,
1047
1097
  debug_output: @debug_output)
1098
+ @last_communicated = nil
1048
1099
  on_connect
1049
1100
  rescue => exception
1050
1101
  if s
1051
- D "Conn close because of connect error #{exception}"
1102
+ debug "Conn close because of connect error #{exception}"
1052
1103
  s.close
1053
1104
  end
1054
1105
  raise
@@ -1180,7 +1231,8 @@ module Net #:nodoc:
1180
1231
  # The username of the proxy server, if one is configured.
1181
1232
  def proxy_user
1182
1233
  if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1183
- proxy_uri&.user
1234
+ user = proxy_uri&.user
1235
+ unescape(user) if user
1184
1236
  else
1185
1237
  @proxy_user
1186
1238
  end
@@ -1189,7 +1241,8 @@ module Net #:nodoc:
1189
1241
  # The password of the proxy server, if one is configured.
1190
1242
  def proxy_pass
1191
1243
  if ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE && @proxy_from_env
1192
- proxy_uri&.password
1244
+ pass = proxy_uri&.password
1245
+ unescape(pass) if pass
1193
1246
  else
1194
1247
  @proxy_pass
1195
1248
  end
@@ -1200,6 +1253,11 @@ module Net #:nodoc:
1200
1253
 
1201
1254
  private
1202
1255
 
1256
+ def unescape(value)
1257
+ require 'cgi/util'
1258
+ CGI.unescape(value)
1259
+ end
1260
+
1203
1261
  # without proxy, obsolete
1204
1262
 
1205
1263
  def conn_address # :nodoc:
@@ -1556,6 +1614,8 @@ module Net #:nodoc:
1556
1614
  begin
1557
1615
  res = HTTPResponse.read_new(@socket)
1558
1616
  res.decode_content = req.decode_content
1617
+ res.body_encoding = @response_body_encoding
1618
+ res.ignore_eof = @ignore_eof
1559
1619
  end while res.kind_of?(HTTPInformation)
1560
1620
 
1561
1621
  res.uri = req.uri
@@ -1575,10 +1635,10 @@ module Net #:nodoc:
1575
1635
  if count < max_retries && IDEMPOTENT_METHODS_.include?(req.method)
1576
1636
  count += 1
1577
1637
  @socket.close if @socket
1578
- D "Conn close because of error #{exception}, and retry"
1638
+ debug "Conn close because of error #{exception}, and retry"
1579
1639
  retry
1580
1640
  end
1581
- D "Conn close because of error #{exception}"
1641
+ debug "Conn close because of error #{exception}"
1582
1642
  @socket.close if @socket
1583
1643
  raise
1584
1644
  end
@@ -1586,7 +1646,7 @@ module Net #:nodoc:
1586
1646
  end_transport req, res
1587
1647
  res
1588
1648
  rescue => exception
1589
- D "Conn close because of error #{exception}"
1649
+ debug "Conn close because of error #{exception}"
1590
1650
  @socket.close if @socket
1591
1651
  raise exception
1592
1652
  end
@@ -1596,11 +1656,11 @@ module Net #:nodoc:
1596
1656
  connect
1597
1657
  elsif @last_communicated
1598
1658
  if @last_communicated + @keep_alive_timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
1599
- D 'Conn close because of keep_alive_timeout'
1659
+ debug 'Conn close because of keep_alive_timeout'
1600
1660
  @socket.close
1601
1661
  connect
1602
1662
  elsif @socket.io.to_io.wait_readable(0) && @socket.eof?
1603
- D "Conn close because of EOF"
1663
+ debug "Conn close because of EOF"
1604
1664
  @socket.close
1605
1665
  connect
1606
1666
  end
@@ -1618,15 +1678,15 @@ module Net #:nodoc:
1618
1678
  @curr_http_version = res.http_version
1619
1679
  @last_communicated = nil
1620
1680
  if @socket.closed?
1621
- D 'Conn socket closed'
1681
+ debug 'Conn socket closed'
1622
1682
  elsif not res.body and @close_on_empty_response
1623
- D 'Conn close'
1683
+ debug 'Conn close'
1624
1684
  @socket.close
1625
1685
  elsif keep_alive?(req, res)
1626
- D 'Conn keep-alive'
1686
+ debug 'Conn keep-alive'
1627
1687
  @last_communicated = Process.clock_gettime(Process::CLOCK_MONOTONIC)
1628
1688
  else
1629
- D 'Conn close'
1689
+ debug 'Conn close'
1630
1690
  @socket.close
1631
1691
  end
1632
1692
  end
@@ -1681,11 +1741,14 @@ module Net #:nodoc:
1681
1741
  default_port == port ? addr : "#{addr}:#{port}"
1682
1742
  end
1683
1743
 
1684
- def D(msg)
1744
+ # Adds a message to debugging output
1745
+ def debug(msg)
1685
1746
  return unless @debug_output
1686
1747
  @debug_output << msg
1687
1748
  @debug_output << "\n"
1688
1749
  end
1750
+
1751
+ alias_method :D, :debug
1689
1752
  end
1690
1753
 
1691
1754
  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.1.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - NARUSE, Yui
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-22 00:00:00.000000000 Z
11
+ date: 2022-05-09 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.2.2
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