httpx 0.24.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +0 -48
  3. data/README.md +4 -13
  4. data/doc/release_notes/0_24_4.md +3 -3
  5. data/doc/release_notes/0_24_6.md +5 -0
  6. data/doc/release_notes/1_0_0.md +60 -0
  7. data/lib/httpx/adapters/datadog.rb +28 -97
  8. data/lib/httpx/adapters/faraday.rb +9 -52
  9. data/lib/httpx/adapters/webmock.rb +2 -7
  10. data/lib/httpx/altsvc.rb +4 -22
  11. data/lib/httpx/base64.rb +27 -0
  12. data/lib/httpx/chainable.rb +2 -25
  13. data/lib/httpx/connection.rb +11 -32
  14. data/lib/httpx/domain_name.rb +5 -12
  15. data/lib/httpx/errors.rb +0 -2
  16. data/lib/httpx/extensions.rb +0 -124
  17. data/lib/httpx/io/ssl.rb +26 -59
  18. data/lib/httpx/io/tcp.rb +27 -68
  19. data/lib/httpx/io/udp.rb +13 -48
  20. data/lib/httpx/io/unix.rb +1 -8
  21. data/lib/httpx/loggable.rb +4 -19
  22. data/lib/httpx/options.rb +24 -84
  23. data/lib/httpx/plugins/{authentication → auth}/basic.rb +1 -5
  24. data/lib/httpx/plugins/{authentication → auth}/digest.rb +2 -5
  25. data/lib/httpx/plugins/{authentication → auth}/ntlm.rb +1 -3
  26. data/lib/httpx/plugins/{authentication → auth}/socks5.rb +0 -2
  27. data/lib/httpx/plugins/auth.rb +25 -0
  28. data/lib/httpx/plugins/aws_sigv4.rb +0 -1
  29. data/lib/httpx/plugins/{basic_authentication.rb → basic_auth.rb} +5 -6
  30. data/lib/httpx/plugins/brotli.rb +50 -0
  31. data/lib/httpx/plugins/circuit_breaker/circuit.rb +40 -16
  32. data/lib/httpx/plugins/circuit_breaker/circuit_store.rb +16 -5
  33. data/lib/httpx/plugins/circuit_breaker.rb +11 -4
  34. data/lib/httpx/plugins/cookies/set_cookie_parser.rb +0 -2
  35. data/lib/httpx/plugins/cookies.rb +1 -1
  36. data/lib/httpx/plugins/{digest_authentication.rb → digest_auth.rb} +5 -5
  37. data/lib/httpx/plugins/follow_redirects.rb +21 -24
  38. data/lib/httpx/plugins/grpc/grpc_encoding.rb +82 -0
  39. data/lib/httpx/plugins/grpc/message.rb +7 -39
  40. data/lib/httpx/plugins/grpc.rb +15 -21
  41. data/lib/httpx/plugins/h2c.rb +0 -1
  42. data/lib/httpx/plugins/{ntlm_authentication.rb → ntlm_auth.rb} +5 -5
  43. data/lib/httpx/plugins/oauth.rb +2 -2
  44. data/lib/httpx/plugins/proxy/http.rb +0 -2
  45. data/lib/httpx/plugins/proxy/socks4.rb +0 -4
  46. data/lib/httpx/plugins/proxy/socks5.rb +1 -5
  47. data/lib/httpx/plugins/proxy.rb +3 -32
  48. data/lib/httpx/plugins/retries.rb +3 -4
  49. data/lib/httpx/plugins/stream.rb +4 -6
  50. data/lib/httpx/punycode.rb +9 -291
  51. data/lib/httpx/request/body.rb +145 -0
  52. data/lib/httpx/request.rb +2 -119
  53. data/lib/httpx/resolver/https.rb +1 -1
  54. data/lib/httpx/resolver/native.rb +6 -14
  55. data/lib/httpx/resolver/resolver.rb +1 -1
  56. data/lib/httpx/resolver/system.rb +11 -9
  57. data/lib/httpx/response/body.rb +206 -0
  58. data/lib/httpx/response/buffer.rb +90 -0
  59. data/lib/httpx/response.rb +5 -208
  60. data/lib/httpx/selector.rb +0 -2
  61. data/lib/httpx/session.rb +3 -10
  62. data/lib/httpx/transcoder/body.rb +0 -1
  63. data/lib/httpx/transcoder/deflate.rb +37 -0
  64. data/lib/httpx/transcoder/form.rb +52 -32
  65. data/lib/httpx/transcoder/gzip.rb +74 -0
  66. data/lib/httpx/transcoder/json.rb +2 -4
  67. data/lib/httpx/transcoder/multipart/decoder.rb +139 -0
  68. data/lib/httpx/{plugins → transcoder}/multipart/encoder.rb +3 -3
  69. data/lib/httpx/{plugins → transcoder}/multipart/mime_type_detector.rb +1 -1
  70. data/lib/httpx/{plugins → transcoder}/multipart/part.rb +3 -2
  71. data/lib/httpx/transcoder/multipart.rb +17 -0
  72. data/lib/httpx/transcoder/utils/body_reader.rb +46 -0
  73. data/lib/httpx/transcoder/utils/deflater.rb +72 -0
  74. data/lib/httpx/transcoder/xml.rb +0 -2
  75. data/lib/httpx/transcoder.rb +2 -2
  76. data/lib/httpx/utils.rb +10 -20
  77. data/lib/httpx/version.rb +1 -1
  78. data/lib/httpx.rb +0 -8
  79. data/sig/chainable.rbs +5 -6
  80. data/sig/connection.rbs +0 -1
  81. data/sig/errors.rbs +0 -3
  82. data/sig/httpx.rbs +2 -1
  83. data/sig/io/unix.rbs +1 -1
  84. data/sig/options.rbs +12 -8
  85. data/sig/plugins/{authentication → auth}/basic.rbs +0 -2
  86. data/sig/plugins/auth.rbs +13 -0
  87. data/sig/plugins/{basic_authentication.rbs → basic_auth.rbs} +2 -2
  88. data/sig/plugins/brotli.rbs +22 -0
  89. data/sig/plugins/circuit_breaker.rbs +7 -3
  90. data/sig/plugins/compression.rbs +0 -2
  91. data/sig/plugins/{digest_authentication.rbs → digest_auth.rbs} +2 -2
  92. data/sig/plugins/follow_redirects.rbs +0 -1
  93. data/sig/plugins/grpc/call.rbs +19 -0
  94. data/sig/plugins/grpc/grpc_encoding.rbs +33 -0
  95. data/sig/plugins/grpc/message.rbs +17 -0
  96. data/sig/plugins/grpc.rbs +2 -32
  97. data/sig/plugins/{ntlm_authentication.rbs → ntlm_auth.rbs} +2 -2
  98. data/sig/plugins/oauth.rbs +1 -1
  99. data/sig/plugins/proxy/socks4.rbs +2 -3
  100. data/sig/plugins/proxy/socks5.rbs +0 -1
  101. data/sig/plugins/proxy/ssh.rbs +1 -1
  102. data/sig/plugins/response_cache.rbs +5 -2
  103. data/sig/request/body.rbs +42 -0
  104. data/sig/request.rbs +1 -27
  105. data/sig/resolver/resolver.rbs +1 -1
  106. data/sig/response/body.rbs +52 -0
  107. data/sig/response/buffer.rbs +24 -0
  108. data/sig/response.rbs +0 -39
  109. data/sig/session.rbs +2 -0
  110. data/sig/transcoder/body.rbs +4 -3
  111. data/sig/transcoder/deflate.rbs +11 -0
  112. data/sig/transcoder/form.rbs +5 -3
  113. data/sig/transcoder/gzip.rbs +24 -0
  114. data/sig/transcoder/json.rbs +4 -2
  115. data/sig/{plugins → transcoder}/multipart.rbs +3 -10
  116. data/sig/transcoder/utils/body_reader.rbs +15 -0
  117. data/sig/transcoder/utils/deflater.rbs +29 -0
  118. data/sig/transcoder.rbs +18 -2
  119. metadata +52 -34
  120. data/lib/httpx/plugins/authentication.rb +0 -24
  121. data/lib/httpx/plugins/compression/brotli.rb +0 -54
  122. data/lib/httpx/plugins/compression/deflate.rb +0 -54
  123. data/lib/httpx/plugins/compression/gzip.rb +0 -90
  124. data/lib/httpx/plugins/compression.rb +0 -165
  125. data/lib/httpx/plugins/multipart/decoder.rb +0 -137
  126. data/lib/httpx/plugins/multipart.rb +0 -96
  127. data/sig/plugins/authentication.rbs +0 -13
  128. data/sig/plugins/compression/brotli.rbs +0 -21
  129. data/sig/plugins/compression/deflate.rbs +0 -17
  130. data/sig/plugins/compression/gzip.rbs +0 -29
  131. /data/sig/plugins/{authentication → auth}/digest.rbs +0 -0
  132. /data/sig/plugins/{authentication → auth}/ntlm.rbs +0 -0
  133. /data/sig/plugins/{authentication → auth}/socks5.rbs +0 -0
@@ -1,304 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- begin
5
- require "idnx"
4
+ module Punycode
5
+ module_function
6
6
 
7
- module Punycode
8
- module_function
7
+ begin
8
+ require "idnx"
9
9
 
10
10
  def encode_hostname(hostname)
11
11
  Idnx.to_punycode(hostname)
12
12
  end
13
- end
14
-
15
- rescue LoadError
16
- # :nocov:
17
- # -*- coding: utf-8 -*-
18
- #--
19
- # punycode.rb - PunyCode encoder for the Domain Name library
20
- #
21
- # Copyright (C) 2011-2017 Akinori MUSHA, All rights reserved.
22
- #
23
- # Ported from puny.c, a part of VeriSign XCode (encode/decode) IDN
24
- # Library.
25
- #
26
- # Copyright (C) 2000-2002 Verisign Inc., All rights reserved.
27
- #
28
- # Redistribution and use in source and binary forms, with or
29
- # without modification, are permitted provided that the following
30
- # conditions are met:
31
- #
32
- # 1) Redistributions of source code must retain the above copyright
33
- # notice, this list of conditions and the following disclaimer.
34
- #
35
- # 2) Redistributions in binary form must reproduce the above copyright
36
- # notice, this list of conditions and the following disclaimer in
37
- # the documentation and/or other materials provided with the
38
- # distribution.
39
- #
40
- # 3) Neither the name of the VeriSign Inc. nor the names of its
41
- # contributors may be used to endorse or promote products derived
42
- # from this software without specific prior written permission.
43
- #
44
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45
- # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
46
- # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
47
- # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
48
- # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
49
- # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
50
- # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
51
- # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
52
- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
54
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55
- # POSSIBILITY OF SUCH DAMAGE.
56
- #
57
- # This software is licensed under the BSD open source license. For more
58
- # information visit www.opensource.org.
59
- #
60
- # Authors:
61
- # John Colosi (VeriSign)
62
- # Srikanth Veeramachaneni (VeriSign)
63
- # Nagesh Chigurupati (Verisign)
64
- # Praveen Srinivasan(Verisign)
65
- #++
66
- module Punycode
67
- BASE = 36
68
- TMIN = 1
69
- TMAX = 26
70
- SKEW = 38
71
- DAMP = 700
72
- INITIAL_BIAS = 72
73
- INITIAL_N = 0x80
74
- DELIMITER = "-"
75
-
76
- MAXINT = (1 << 32) - 1
77
-
78
- LOBASE = BASE - TMIN
79
- CUTOFF = LOBASE * TMAX / 2
80
-
81
- RE_NONBASIC = /[^\x00-\x7f]/.freeze
82
-
83
- # Returns the numeric value of a basic code point (for use in
84
- # representing integers) in the range 0 to base-1, or nil if cp
85
- # is does not represent a value.
86
- DECODE_DIGIT = {}.tap do |map|
87
- # ASCII A..Z map to 0..25
88
- # ASCII a..z map to 0..25
89
- (0..25).each { |i| map[65 + i] = map[97 + i] = i }
90
- # ASCII 0..9 map to 26..35
91
- (26..35).each { |i| map[22 + i] = i }
92
- end
93
-
94
- # Returns the basic code point whose value (when used for
95
- # representing integers) is d, which must be in the range 0 to
96
- # BASE-1. The lowercase form is used unless flag is true, in
97
- # which case the uppercase form is used. The behavior is
98
- # undefined if flag is nonzero and digit d has no uppercase
99
- # form.
100
- ENCODE_DIGIT = proc { |d, flag|
101
- (d + 22 + (d < 26 ? 75 : 0) - (flag ? (1 << 5) : 0)).chr
102
- # 0..25 map to ASCII a..z or A..Z
103
- # 26..35 map to ASCII 0..9
104
- }
105
-
106
- DOT = "."
107
- PREFIX = "xn--"
108
-
109
- # Most errors we raise are basically kind of ArgumentError.
110
- class ArgumentError < ::ArgumentError; end
111
- class BufferOverflowError < ArgumentError; end
112
-
113
- module_function
114
-
115
- # Encode a +string+ in Punycode
116
- def encode(string)
117
- input = string.unpack("U*")
118
- output = +""
119
-
120
- # Initialize the state
121
- n = INITIAL_N
122
- delta = 0
123
- bias = INITIAL_BIAS
124
-
125
- # Handle the basic code points
126
- input.each { |cp| output << cp.chr if cp < 0x80 }
127
-
128
- h = b = output.length
129
-
130
- # h is the number of code points that have been handled, b is the
131
- # number of basic code points, and out is the number of characters
132
- # that have been output.
133
-
134
- output << DELIMITER if b > 0
135
-
136
- # Main encoding loop
137
-
138
- while h < input.length
139
- # All non-basic code points < n have been handled already. Find
140
- # the next larger one
141
-
142
- m = MAXINT
143
- input.each do |cp|
144
- m = cp if (n...m) === cp
145
- end
146
-
147
- # Increase delta enough to advance the decoder's <n,i> state to
148
- # <m,0>, but guard against overflow
149
-
150
- delta += (m - n) * (h + 1)
151
- raise BufferOverflowError if delta > MAXINT
152
-
153
- n = m
154
-
155
- input.each do |cp|
156
- # AMC-ACE-Z can use this simplified version instead
157
- if cp < n
158
- delta += 1
159
- raise BufferOverflowError if delta > MAXINT
160
- elsif cp == n
161
- # Represent delta as a generalized variable-length integer
162
- q = delta
163
- k = BASE
164
- loop do
165
- t = k <= bias ? TMIN : k - bias >= TMAX ? TMAX : k - bias
166
- break if q < t
167
-
168
- q, r = (q - t).divmod(BASE - t)
169
- output << ENCODE_DIGIT[t + r, false]
170
- k += BASE
171
- end
172
-
173
- output << ENCODE_DIGIT[q, false]
174
-
175
- # Adapt the bias
176
- delta = h == b ? delta / DAMP : delta >> 1
177
- delta += delta / (h + 1)
178
- bias = 0
179
- while delta > CUTOFF
180
- delta /= LOBASE
181
- bias += BASE
182
- end
183
- bias += (LOBASE + 1) * delta / (delta + SKEW)
184
-
185
- delta = 0
186
- h += 1
187
- end
188
- end
189
-
190
- delta += 1
191
- n += 1
192
- end
193
-
194
- output
195
- end
196
-
197
- # Encode a hostname using IDN/Punycode algorithms
13
+ rescue LoadError
198
14
  def encode_hostname(hostname)
199
- hostname.match(RE_NONBASIC) || (return hostname)
200
-
201
- hostname.split(DOT).map do |name|
202
- if name.match(RE_NONBASIC)
203
- PREFIX + encode(name)
204
- else
205
- name
206
- end
207
- end.join(DOT)
208
- end
209
-
210
- # Decode a +string+ encoded in Punycode
211
- def decode(string)
212
- # Initialize the state
213
- n = INITIAL_N
214
- i = 0
215
- bias = INITIAL_BIAS
216
-
217
- if j = string.rindex(DELIMITER)
218
- b = string[0...j]
219
-
220
- b.match(RE_NONBASIC) &&
221
- raise(ArgumentError, "Illegal character is found in basic part: #{string.inspect}")
222
-
223
- # Handle the basic code points
224
-
225
- output = b.unpack("U*")
226
- u = string[(j + 1)..-1]
227
- else
228
- output = []
229
- u = string
230
- end
231
-
232
- # Main decoding loop: Start just after the last delimiter if any
233
- # basic code points were copied; start at the beginning
234
- # otherwise.
235
-
236
- input = u.unpack("C*")
237
- input_length = input.length
238
- h = 0
239
- out = output.length
240
-
241
- while h < input_length
242
- # Decode a generalized variable-length integer into delta,
243
- # which gets added to i. The overflow checking is easier
244
- # if we increase i as we go, then subtract off its starting
245
- # value at the end to obtain delta.
246
-
247
- oldi = i
248
- w = 1
249
- k = BASE
250
-
251
- loop do
252
- (digit = DECODE_DIGIT[input[h]]) ||
253
- raise(ArgumentError, "Illegal character is found in non-basic part: #{string.inspect}")
254
- h += 1
255
- i += digit * w
256
- raise BufferOverflowError if i > MAXINT
257
-
258
- t = k <= bias ? TMIN : k - bias >= TMAX ? TMAX : k - bias
259
- break if digit < t
260
-
261
- w *= BASE - t
262
- raise BufferOverflowError if w > MAXINT
263
-
264
- k += BASE
265
- (h < input_length) || raise(ArgumentError, "Malformed input given: #{string.inspect}")
266
- end
267
-
268
- # Adapt the bias
269
- delta = oldi == 0 ? i / DAMP : (i - oldi) >> 1
270
- delta += delta / (out + 1)
271
- bias = 0
272
- while delta > CUTOFF
273
- delta /= LOBASE
274
- bias += BASE
275
- end
276
- bias += (LOBASE + 1) * delta / (delta + SKEW)
277
-
278
- # i was supposed to wrap around from out+1 to 0, incrementing
279
- # n each time, so we'll fix that now:
280
-
281
- q, i = i.divmod(out + 1)
282
- n += q
283
- raise BufferOverflowError if n > MAXINT
284
-
285
- # Insert n at position i of the output:
286
-
287
- output[i, 0] = n
288
-
289
- out += 1
290
- i += 1
291
- end
292
- output.pack("U*")
293
- end
15
+ warn "#{hostname} cannot be converted to punycode. Install the " \
16
+ "\"idnx\" gem: https://github.com/HoneyryderChuck/idnx"
294
17
 
295
- # Decode a hostname using IDN/Punycode algorithms
296
- def decode_hostname(hostname)
297
- hostname.gsub(/(\A|#{Regexp.quote(DOT)})#{Regexp.quote(PREFIX)}([^#{Regexp.quote(DOT)}]*)/o) do
298
- Regexp.last_match(1) << decode(Regexp.last_match(2))
299
- end
18
+ hostname
300
19
  end
301
20
  end
302
- # :nocov:
303
21
  end
304
- end
22
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ class Request::Body < SimpleDelegator
5
+ class << self
6
+ def new(_, options)
7
+ return options.body if options.body.is_a?(self)
8
+
9
+ super
10
+ end
11
+ end
12
+
13
+ attr_reader :threshold_size
14
+
15
+ def initialize(headers, options)
16
+ @headers = headers
17
+ @threshold_size = options.body_threshold_size
18
+
19
+ # forego compression in the Range cases
20
+ if @headers.key?("range")
21
+ @headers.delete("accept-encoding")
22
+ else
23
+ @headers["accept-encoding"] ||= options.supported_compression_formats
24
+ end
25
+
26
+ initialize_body(options)
27
+
28
+ return if @body.nil?
29
+
30
+ @headers["content-type"] ||= @body.content_type
31
+ @headers["content-length"] = @body.bytesize unless unbounded_body?
32
+ super(@body)
33
+ end
34
+
35
+ def each(&block)
36
+ return enum_for(__method__) unless block
37
+ return if @body.nil?
38
+
39
+ body = stream(@body)
40
+ if body.respond_to?(:read)
41
+ ::IO.copy_stream(body, ProcIO.new(block))
42
+ elsif body.respond_to?(:each)
43
+ body.each(&block)
44
+ else
45
+ block[body.to_s]
46
+ end
47
+ end
48
+
49
+ def rewind
50
+ return if empty?
51
+
52
+ @body.rewind if @body.respond_to?(:rewind)
53
+ end
54
+
55
+ def empty?
56
+ return true if @body.nil?
57
+ return false if chunked?
58
+
59
+ @body.bytesize.zero?
60
+ end
61
+
62
+ def bytesize
63
+ return 0 if @body.nil?
64
+
65
+ @body.bytesize
66
+ end
67
+
68
+ def stream(body)
69
+ encoded = body
70
+ encoded = Transcoder::Chunker.encode(body.enum_for(:each)) if chunked?
71
+ encoded
72
+ end
73
+
74
+ def unbounded_body?
75
+ return @unbounded_body if defined?(@unbounded_body)
76
+
77
+ @unbounded_body = !@body.nil? && (chunked? || @body.bytesize == Float::INFINITY)
78
+ end
79
+
80
+ def chunked?
81
+ @headers["transfer-encoding"] == "chunked"
82
+ end
83
+
84
+ def chunk!
85
+ @headers.add("transfer-encoding", "chunked")
86
+ end
87
+
88
+ # :nocov:
89
+ def inspect
90
+ "#<HTTPX::Request::Body:#{object_id} " \
91
+ "#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
92
+ end
93
+ # :nocov:
94
+
95
+ private
96
+
97
+ def initialize_body(options)
98
+ @body = if options.body
99
+ Transcoder::Body.encode(options.body)
100
+ elsif options.form
101
+ Transcoder::Form.encode(options.form)
102
+ elsif options.json
103
+ Transcoder::JSON.encode(options.json)
104
+ elsif options.xml
105
+ Transcoder::Xml.encode(options.xml)
106
+ end
107
+
108
+ return unless @body
109
+
110
+ return unless options.compress_request_body
111
+
112
+ return unless @headers.key?("content-encoding")
113
+
114
+ @headers.get("content-encoding").each do |encoding|
115
+ @body = self.class.initialize_deflater_body(@body, encoding)
116
+ end
117
+ end
118
+
119
+ class << self
120
+ def initialize_deflater_body(body, encoding)
121
+ case encoding
122
+ when "gzip"
123
+ Transcoder::GZIP.encode(body)
124
+ when "deflate"
125
+ Transcoder::Deflate.encode(body)
126
+ when "identity"
127
+ body
128
+ else
129
+ body
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ class ProcIO
136
+ def initialize(block)
137
+ @block = block
138
+ end
139
+
140
+ def write(data)
141
+ @block.call(data.dup)
142
+ data.bytesize
143
+ end
144
+ end
145
+ end
data/lib/httpx/request.rb CHANGED
@@ -19,10 +19,6 @@ module HTTPX
19
19
  def_delegator :@body, :empty?
20
20
 
21
21
  def initialize(verb, uri, options = {})
22
- if verb.is_a?(Symbol)
23
- warn "DEPRECATION WARNING: Using symbols for `verb` is deprecated, and will not be supported in httpx 1.0. " \
24
- "Use \"#{verb.to_s.upcase}\" instead."
25
- end
26
22
  @verb = verb.to_s.upcase
27
23
  @options = Options.new(options)
28
24
  @uri = Utils.to_uri(uri)
@@ -69,16 +65,6 @@ module HTTPX
69
65
  :w
70
66
  end
71
67
 
72
- if RUBY_VERSION < "2.2"
73
- URIParser = URI::DEFAULT_PARSER
74
-
75
- def initialize_with_escape(verb, uri, options = {})
76
- initialize_without_escape(verb, URIParser.escape(uri.to_s), options)
77
- end
78
- alias_method :initialize_without_escape, :initialize
79
- alias_method :initialize, :initialize_with_escape
80
- end
81
-
82
68
  def merge_headers(h)
83
69
  @headers = @headers.merge(h)
84
70
  end
@@ -153,100 +139,6 @@ module HTTPX
153
139
  end
154
140
  # :nocov:
155
141
 
156
- class Body < SimpleDelegator
157
- class << self
158
- def new(_, options)
159
- return options.body if options.body.is_a?(self)
160
-
161
- super
162
- end
163
- end
164
-
165
- def initialize(headers, options)
166
- @headers = headers
167
- @body = initialize_body(options)
168
- return if @body.nil?
169
-
170
- @headers["content-type"] ||= @body.content_type
171
- @headers["content-length"] = @body.bytesize unless unbounded_body?
172
- super(@body)
173
- end
174
-
175
- def each(&block)
176
- return enum_for(__method__) unless block
177
- return if @body.nil?
178
-
179
- body = stream(@body)
180
- if body.respond_to?(:read)
181
- ::IO.copy_stream(body, ProcIO.new(block))
182
- elsif body.respond_to?(:each)
183
- body.each(&block)
184
- else
185
- block[body.to_s]
186
- end
187
- end
188
-
189
- def rewind
190
- return if empty?
191
-
192
- @body.rewind if @body.respond_to?(:rewind)
193
- end
194
-
195
- def empty?
196
- return true if @body.nil?
197
- return false if chunked?
198
-
199
- @body.bytesize.zero?
200
- end
201
-
202
- def bytesize
203
- return 0 if @body.nil?
204
-
205
- @body.bytesize
206
- end
207
-
208
- def stream(body)
209
- encoded = body
210
- encoded = Transcoder::Chunker.encode(body.enum_for(:each)) if chunked?
211
- encoded
212
- end
213
-
214
- def unbounded_body?
215
- return @unbounded_body if defined?(@unbounded_body)
216
-
217
- @unbounded_body = !@body.nil? && (chunked? || @body.bytesize == Float::INFINITY)
218
- end
219
-
220
- def chunked?
221
- @headers["transfer-encoding"] == "chunked"
222
- end
223
-
224
- def chunk!
225
- @headers.add("transfer-encoding", "chunked")
226
- end
227
-
228
- # :nocov:
229
- def inspect
230
- "#<HTTPX::Request::Body:#{object_id} " \
231
- "#{unbounded_body? ? "stream" : "@bytesize=#{bytesize}"}>"
232
- end
233
- # :nocov:
234
-
235
- private
236
-
237
- def initialize_body(options)
238
- if options.body
239
- Transcoder::Body.encode(options.body)
240
- elsif options.form
241
- Transcoder::Form.encode(options.form)
242
- elsif options.json
243
- Transcoder::JSON.encode(options.json)
244
- elsif options.xml
245
- Transcoder::Xml.encode(options.xml)
246
- end
247
- end
248
- end
249
-
250
142
  def transition(nextstate)
251
143
  case nextstate
252
144
  when :idle
@@ -284,16 +176,7 @@ module HTTPX
284
176
  def expects?
285
177
  @headers["expect"] == "100-continue" && @informational_status == 100 && !@response
286
178
  end
287
-
288
- class ProcIO
289
- def initialize(block)
290
- @block = block
291
- end
292
-
293
- def write(data)
294
- @block.call(data.dup)
295
- data.bytesize
296
- end
297
- end
298
179
  end
299
180
  end
181
+
182
+ require_relative "request/body"
@@ -4,12 +4,12 @@ require "resolv"
4
4
  require "uri"
5
5
  require "cgi"
6
6
  require "forwardable"
7
+ require "httpx/base64"
7
8
 
8
9
  module HTTPX
9
10
  class Resolver::HTTPS < Resolver::Resolver
10
11
  extend Forwardable
11
12
  using URIExtensions
12
- using StringExtensions
13
13
 
14
14
  module DNSExtensions
15
15
  refine Resolv::DNS do
@@ -8,20 +8,12 @@ module HTTPX
8
8
  extend Forwardable
9
9
  using URIExtensions
10
10
 
11
- DEFAULTS = if RUBY_VERSION < "2.2"
12
- {
13
- **Resolv::DNS::Config.default_config_hash,
14
- packet_size: 512,
15
- timeouts: Resolver::RESOLVE_TIMEOUT,
16
- }
17
- else
18
- {
19
- nameserver: nil,
20
- **Resolv::DNS::Config.default_config_hash,
21
- packet_size: 512,
22
- timeouts: Resolver::RESOLVE_TIMEOUT,
23
- }
24
- end.freeze
11
+ DEFAULTS = {
12
+ nameserver: nil,
13
+ **Resolv::DNS::Config.default_config_hash,
14
+ packet_size: 512,
15
+ timeouts: Resolver::RESOLVE_TIMEOUT,
16
+ }.freeze
25
17
 
26
18
  DNS_PORT = 53
27
19
 
@@ -95,7 +95,7 @@ module HTTPX
95
95
  end
96
96
 
97
97
  def resolve_error(hostname, ex = nil)
98
- return ex if ex.is_a?(ResolveError)
98
+ return ex if ex.is_a?(ResolveError) || ex.is_a?(ResolveTimeoutError)
99
99
 
100
100
  message = ex ? ex.message : "Can't resolve #{hostname}"
101
101
  error = ResolveError.new(message)
@@ -92,6 +92,12 @@ module HTTPX
92
92
  resolve
93
93
  end
94
94
 
95
+ def raise_timeout_error(interval)
96
+ error = HTTPX::ResolveTimeoutError.new(interval, "timed out while waiting on select")
97
+ error.set_backtrace(caller)
98
+ on_error(error)
99
+ end
100
+
95
101
  private
96
102
 
97
103
  def transition(nextstate)
@@ -164,6 +170,7 @@ module HTTPX
164
170
  Thread.current.report_on_exception = false
165
171
  begin
166
172
  addrs = if resolve_timeout
173
+
167
174
  Timeout.timeout(resolve_timeout) do
168
175
  __addrinfo_resolve(hostname, scheme)
169
176
  end
@@ -182,16 +189,11 @@ module HTTPX
182
189
  @pipe_write.putc(DONE) unless @pipe_write.closed?
183
190
  end
184
191
  end
185
- rescue Timeout::Error => e
186
- ex = ResolveTimeoutError.new(resolve_timeout, e.message)
187
- ex.set_backtrace(ex.backtrace)
188
- @pipe_mutex.synchronize do
189
- families.each do |family|
190
- @ips.unshift([family, connection, ex])
191
- @pipe_write.putc(ERROR) unless @pipe_write.closed?
192
- end
193
- end
194
192
  rescue StandardError => e
193
+ if e.is_a?(Timeout::Error)
194
+ e = ResolveTimeoutError.new(resolve_timeout, e.message)
195
+ e.set_backtrace(e.backtrace)
196
+ end
195
197
  @pipe_mutex.synchronize do
196
198
  families.each do |family|
197
199
  @ips.unshift([family, connection, e])