httpx 0.21.0 → 0.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +53 -35
  3. data/doc/release_notes/0_10_0.md +2 -2
  4. data/doc/release_notes/0_11_0.md +3 -5
  5. data/doc/release_notes/0_12_0.md +5 -5
  6. data/doc/release_notes/0_13_0.md +4 -4
  7. data/doc/release_notes/0_14_0.md +2 -2
  8. data/doc/release_notes/0_16_0.md +3 -3
  9. data/doc/release_notes/0_17_0.md +1 -1
  10. data/doc/release_notes/0_18_0.md +4 -4
  11. data/doc/release_notes/0_18_2.md +1 -1
  12. data/doc/release_notes/0_19_0.md +1 -1
  13. data/doc/release_notes/0_20_0.md +1 -1
  14. data/doc/release_notes/0_21_0.md +7 -5
  15. data/doc/release_notes/0_21_1.md +12 -0
  16. data/doc/release_notes/0_22_0.md +13 -0
  17. data/doc/release_notes/0_22_1.md +11 -0
  18. data/doc/release_notes/0_22_2.md +5 -0
  19. data/doc/release_notes/0_22_3.md +55 -0
  20. data/doc/release_notes/0_22_4.md +6 -0
  21. data/lib/httpx/adapters/datadog.rb +1 -1
  22. data/lib/httpx/adapters/faraday.rb +12 -4
  23. data/lib/httpx/adapters/sentry.rb +6 -2
  24. data/lib/httpx/connection/http2.rb +1 -1
  25. data/lib/httpx/connection.rb +34 -6
  26. data/lib/httpx/errors.rb +2 -0
  27. data/lib/httpx/extensions.rb +10 -1
  28. data/lib/httpx/io/tcp.rb +2 -1
  29. data/lib/httpx/io/udp.rb +4 -5
  30. data/lib/httpx/options.rb +2 -2
  31. data/lib/httpx/plugins/authentication.rb +1 -1
  32. data/lib/httpx/plugins/aws_sigv4.rb +2 -2
  33. data/lib/httpx/plugins/basic_authentication.rb +1 -1
  34. data/lib/httpx/plugins/circuit_breaker/circuit.rb +1 -1
  35. data/lib/httpx/plugins/circuit_breaker.rb +1 -1
  36. data/lib/httpx/plugins/compression/gzip.rb +1 -1
  37. data/lib/httpx/plugins/compression.rb +4 -4
  38. data/lib/httpx/plugins/cookies.rb +1 -1
  39. data/lib/httpx/plugins/digest_authentication.rb +3 -1
  40. data/lib/httpx/plugins/expect.rb +4 -3
  41. data/lib/httpx/plugins/follow_redirects.rb +8 -1
  42. data/lib/httpx/plugins/grpc/message.rb +1 -1
  43. data/lib/httpx/plugins/grpc.rb +1 -1
  44. data/lib/httpx/plugins/h2c.rb +1 -1
  45. data/lib/httpx/plugins/multipart/decoder.rb +7 -57
  46. data/lib/httpx/plugins/multipart.rb +2 -2
  47. data/lib/httpx/plugins/ntlm_authentication.rb +3 -1
  48. data/lib/httpx/plugins/persistent.rb +1 -1
  49. data/lib/httpx/plugins/proxy/http.rb +4 -2
  50. data/lib/httpx/plugins/proxy.rb +1 -1
  51. data/lib/httpx/plugins/push_promise.rb +1 -1
  52. data/lib/httpx/plugins/rate_limiter.rb +3 -1
  53. data/lib/httpx/plugins/response_cache.rb +1 -1
  54. data/lib/httpx/plugins/retries.rb +3 -2
  55. data/lib/httpx/plugins/stream.rb +0 -2
  56. data/lib/httpx/plugins/upgrade.rb +3 -1
  57. data/lib/httpx/plugins/webdav.rb +2 -0
  58. data/lib/httpx/pool.rb +41 -2
  59. data/lib/httpx/request.rb +1 -1
  60. data/lib/httpx/resolver/https.rb +16 -2
  61. data/lib/httpx/resolver/native.rb +28 -26
  62. data/lib/httpx/resolver/resolver.rb +9 -8
  63. data/lib/httpx/resolver.rb +8 -0
  64. data/lib/httpx/response.rb +8 -0
  65. data/lib/httpx/transcoder/xml.rb +0 -2
  66. data/lib/httpx/transcoder.rb +1 -1
  67. data/lib/httpx/utils.rb +30 -0
  68. data/lib/httpx/version.rb +1 -1
  69. data/lib/httpx.rb +6 -0
  70. data/sig/connection.rbs +3 -1
  71. data/sig/plugins/multipart.rbs +0 -2
  72. data/sig/pool.rbs +3 -1
  73. data/sig/resolver/https.rbs +3 -2
  74. data/sig/resolver/native.rbs +2 -1
  75. data/sig/resolver/resolver.rbs +3 -1
  76. data/sig/resolver.rbs +1 -1
  77. data/sig/response.rbs +4 -1
  78. data/sig/utils.rbs +2 -0
  79. metadata +21 -9
@@ -63,7 +63,11 @@ module HTTPX::Plugins
63
63
 
64
64
  request_info = extract_request_info(req)
65
65
  sentry_span.set_description("#{request_info[:method]} #{request_info[:url]}")
66
- sentry_span.set_data(:status, res.status)
66
+ if res.is_a?(HTTPX::ErrorResponse)
67
+ sentry_span.set_data(:error, res.message)
68
+ else
69
+ sentry_span.set_data(:status, res.status)
70
+ end
67
71
  sentry_span.set_timestamp(::Sentry.utc_now.to_f)
68
72
  end
69
73
 
@@ -95,7 +99,7 @@ module HTTPX::Plugins
95
99
  end
96
100
 
97
101
  Sentry.register_patch do
98
- sentry_session = ::HTTPX.plugin(HTTPX::Plugins::Sentry)
102
+ sentry_session = HTTPX.plugin(HTTPX::Plugins::Sentry)
99
103
 
100
104
  HTTPX.send(:remove_const, :Session)
101
105
  HTTPX.send(:const_set, :Session, sentry_session.class)
@@ -365,7 +365,7 @@ module HTTPX
365
365
  ex.set_backtrace(caller)
366
366
  handle_error(ex)
367
367
  end
368
- return unless is_connection_closed && @streams.size.zero?
368
+ return unless is_connection_closed && @streams.empty?
369
369
 
370
370
  emit(:close, is_connection_closed)
371
371
  end
@@ -45,10 +45,12 @@ module HTTPX
45
45
 
46
46
  def_delegator :@write_buffer, :empty?
47
47
 
48
- attr_reader :io, :origin, :origins, :state, :pending, :options
48
+ attr_reader :type, :io, :origin, :origins, :state, :pending, :options
49
49
 
50
50
  attr_writer :timers
51
51
 
52
+ attr_accessor :family
53
+
52
54
  def initialize(type, uri, options)
53
55
  @type = type
54
56
  @origins = [uri.origin]
@@ -114,7 +116,10 @@ module HTTPX
114
116
 
115
117
  return false unless connection.addresses
116
118
 
117
- !(@io.addresses & connection.addresses).empty? && @options == connection.options
119
+ (
120
+ (open? && @origin == connection.origin) ||
121
+ !(@io.addresses & connection.addresses).empty?
122
+ ) && @options == connection.options
118
123
  end
119
124
 
120
125
  # coalescable connections need to be mergeable!
@@ -219,6 +224,14 @@ module HTTPX
219
224
  @parser.close if @parser
220
225
  end
221
226
 
227
+ # bypasses the state machine to force closing of connections still connecting.
228
+ # **only** used for Happy Eyeballs v2.
229
+ def force_reset
230
+ @state = :closing
231
+ transition(:closed)
232
+ emit(:close)
233
+ end
234
+
222
235
  def reset
223
236
  transition(:closing)
224
237
  transition(:closed)
@@ -309,7 +322,7 @@ module HTTPX
309
322
  # * the number of inflight requests
310
323
  # * the number of pending requests
311
324
  # * whether the write buffer has bytes (i.e. for close handshake)
312
- if @pending.size.zero? && @inflight.zero? && @write_buffer.empty?
325
+ if @pending.empty? && @inflight.zero? && @write_buffer.empty?
313
326
  log(level: 3) { "NO MORE REQUESTS..." }
314
327
  return
315
328
  end
@@ -353,7 +366,7 @@ module HTTPX
353
366
  break if @state == :closing || @state == :closed
354
367
 
355
368
  # exit #consume altogether if all outstanding requests have been dealt with
356
- return if @pending.size.zero? && @inflight.zero?
369
+ return if @pending.empty? && @inflight.zero?
357
370
  end unless ((ints = interests).nil? || ints == :w || @state == :closing) && !epiped
358
371
 
359
372
  #
@@ -512,10 +525,23 @@ module HTTPX
512
525
 
513
526
  def transition(nextstate)
514
527
  handle_transition(nextstate)
515
- rescue Errno::ECONNREFUSED,
528
+ rescue Errno::ECONNABORTED,
529
+ Errno::ECONNREFUSED,
530
+ Errno::ECONNRESET,
516
531
  Errno::EADDRNOTAVAIL,
517
532
  Errno::EHOSTUNREACH,
518
- TLSError => e
533
+ Errno::EINVAL,
534
+ Errno::ENETUNREACH,
535
+ Errno::EPIPE,
536
+ Errno::ENOENT,
537
+ SocketError => e
538
+ # connect errors, exit gracefully
539
+ error = ConnectionError.new(e.message)
540
+ error.set_backtrace(e.backtrace)
541
+ connecting? && callbacks(:connect_error).any? ? emit(:connect_error, error) : handle_error(error)
542
+ @state = :closed
543
+ emit(:close)
544
+ rescue TLSError => e
519
545
  # connect errors, exit gracefully
520
546
  handle_error(e)
521
547
  @state = :closed
@@ -531,6 +557,8 @@ module HTTPX
531
557
  return if @state == :closed
532
558
 
533
559
  @io.connect
560
+ emit(:tcp_open, self) if @io.state == :connected
561
+
534
562
  return unless @io.connected?
535
563
 
536
564
  @connected_at = Utils.now
data/lib/httpx/errors.rb CHANGED
@@ -5,6 +5,8 @@ module HTTPX
5
5
 
6
6
  class UnsupportedSchemeError < Error; end
7
7
 
8
+ class ConnectionError < Error; end
9
+
8
10
  class TimeoutError < Error
9
11
  attr_reader :timeout
10
12
 
@@ -55,6 +55,7 @@ module HTTPX
55
55
  end
56
56
 
57
57
  module NumericExtensions
58
+ # Ruby 2.4 backport
58
59
  refine Numeric do
59
60
  def infinite?
60
61
  self == Float::INFINITY
@@ -64,6 +65,7 @@ module HTTPX
64
65
 
65
66
  module StringExtensions
66
67
  refine String do
68
+ # Ruby 2.5 backport
67
69
  def delete_suffix!(suffix)
68
70
  suffix = Backports.coerce_to_str(suffix)
69
71
  chomp! if frozen?
@@ -80,6 +82,7 @@ module HTTPX
80
82
 
81
83
  module HashExtensions
82
84
  refine Hash do
85
+ # Ruby 2.4 backport
83
86
  def compact
84
87
  h = {}
85
88
  each do |key, value|
@@ -93,7 +96,7 @@ module HTTPX
93
96
  module ArrayExtensions
94
97
  module FilterMap
95
98
  refine Array do
96
-
99
+ # Ruby 2.7 backport
97
100
  def filter_map
98
101
  return to_enum(:filter_map) unless block_given?
99
102
 
@@ -107,6 +110,7 @@ module HTTPX
107
110
 
108
111
  module Sum
109
112
  refine Array do
113
+ # Ruby 2.6 backport
110
114
  def sum(accumulator = 0, &block)
111
115
  values = block_given? ? map(&block) : self
112
116
  values.inject(accumulator, :+)
@@ -116,6 +120,7 @@ module HTTPX
116
120
 
117
121
  module Intersect
118
122
  refine Array do
123
+ # Ruby 3.1 backport
119
124
  def intersect?(arr)
120
125
  if size < arr.size
121
126
  smaller = self
@@ -130,6 +135,7 @@ module HTTPX
130
135
 
131
136
  module IOExtensions
132
137
  refine IO do
138
+ # Ruby 2.3 backport
133
139
  # provides a fallback for rubies where IO#wait isn't implemented,
134
140
  # but IO#wait_readable and IO#wait_writable are.
135
141
  def wait(timeout = nil, _mode = :read_write)
@@ -144,6 +150,7 @@ module HTTPX
144
150
 
145
151
  module RegexpExtensions
146
152
  refine(Regexp) do
153
+ # Ruby 2.4 backport
147
154
  def match?(*args)
148
155
  !match(*args).nil?
149
156
  end
@@ -151,7 +158,9 @@ module HTTPX
151
158
  end
152
159
 
153
160
  module URIExtensions
161
+ # uri 0.11 backport, ships with ruby 3.1
154
162
  refine URI::Generic do
163
+
155
164
  def non_ascii_hostname
156
165
  @non_ascii_hostname
157
166
  end
data/lib/httpx/io/tcp.rb CHANGED
@@ -74,7 +74,8 @@ module HTTPX
74
74
  try_connect
75
75
  rescue Errno::ECONNREFUSED,
76
76
  Errno::EADDRNOTAVAIL,
77
- Errno::EHOSTUNREACH => e
77
+ Errno::EHOSTUNREACH,
78
+ SocketError => e
78
79
  raise e if @ip_index <= 0
79
80
 
80
81
  log { "failed connecting to #{@ip} (#{e.message}), trying next..." }
data/lib/httpx/io/udp.rb CHANGED
@@ -6,11 +6,10 @@ module HTTPX
6
6
  class UDP
7
7
  include Loggable
8
8
 
9
- def initialize(uri, _, options)
10
- ip = IPAddr.new(uri.host)
11
- @host = ip.to_s
12
- @port = uri.port
13
- @io = UDPSocket.new(ip.family)
9
+ def initialize(ip, port, options)
10
+ @host = ip
11
+ @port = port
12
+ @io = UDPSocket.new(IPAddr.new(ip).family)
14
13
  @options = options
15
14
  end
16
15
 
data/lib/httpx/options.rb CHANGED
@@ -15,7 +15,7 @@ module HTTPX
15
15
  # https://github.com/ruby/resolv/blob/095f1c003f6073730500f02acbdbc55f83d70987/lib/resolv.rb#L408
16
16
  ip_address_families = begin
17
17
  list = Socket.ip_address_list
18
- if list.any? { |a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? }
18
+ if list.any? { |a| a.ipv6? && !a.ipv6_loopback? && !a.ipv6_linklocal? && !a.ipv6_unique_local? }
19
19
  [Socket::AF_INET6, Socket::AF_INET]
20
20
  else
21
21
  [Socket::AF_INET]
@@ -100,7 +100,7 @@ module HTTPX
100
100
  end
101
101
 
102
102
  def def_option(optname, *args, &block)
103
- if args.size.zero? && !block
103
+ if args.empty? && !block
104
104
  class_eval(<<-OUT, __FILE__, __LINE__ + 1)
105
105
  def option_#{optname}(v); v; end # def option_smth(v); v; end
106
106
  OUT
@@ -6,7 +6,7 @@ module HTTPX
6
6
  # This plugin adds a shim +authentication+ method to the session, which will fill
7
7
  # the HTTP Authorization header.
8
8
  #
9
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#authentication
9
+ # https://gitlab.com/os85/httpx/wikis/Authentication#authentication
10
10
  #
11
11
  module Authentication
12
12
  module InstanceMethods
@@ -7,7 +7,7 @@ module HTTPX
7
7
  #
8
8
  # https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
9
9
  #
10
- # https://gitlab.com/honeyryderchuck/httpx/wikis/AWS-SigV4
10
+ # https://gitlab.com/os85/httpx/wikis/AWS-SigV4
11
11
  #
12
12
  module AWSSigV4
13
13
  Credentials = Struct.new(:username, :password, :security_token)
@@ -115,7 +115,7 @@ module HTTPX
115
115
  elsif value.respond_to?(:each)
116
116
  digest = OpenSSL::Digest.new(@algorithm)
117
117
 
118
- mb_buffer = value.each.each_with_object("".b) do |chunk, buffer|
118
+ mb_buffer = value.each.with_object("".b) do |chunk, buffer|
119
119
  buffer << chunk
120
120
  break if buffer.bytesize >= 1024 * 1024
121
121
  end
@@ -5,7 +5,7 @@ module HTTPX
5
5
  #
6
6
  # This plugin adds helper methods to implement HTTP Basic Auth (https://tools.ietf.org/html/rfc7617)
7
7
  #
8
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#basic-authentication
8
+ # https://gitlab.com/os85/httpx/wikis/Authentication#basic-authentication
9
9
  #
10
10
  module BasicAuth
11
11
  class << self
@@ -28,7 +28,7 @@ module HTTPX
28
28
  nil
29
29
  when :half_open
30
30
  # return nothing or smth based on ratio
31
- return if Random::DEFAULT.rand >= @circuit_breaker_half_open_drip_rate
31
+ return if Random.rand >= @circuit_breaker_half_open_drip_rate
32
32
 
33
33
  @response
34
34
  when :open
@@ -5,7 +5,7 @@ module HTTPX
5
5
  #
6
6
  # This plugin implements a circuit breaker around connection errors.
7
7
  #
8
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Circuit-Breaker
8
+ # https://gitlab.com/os85/httpx/wikis/Circuit-Breaker
9
9
  #
10
10
  module CircuitBreaker
11
11
  using URIExtensions
@@ -56,7 +56,7 @@ module HTTPX
56
56
 
57
57
  class Inflater
58
58
  def initialize(bytesize)
59
- @inflater = Zlib::Inflate.new(32 + Zlib::MAX_WBITS)
59
+ @inflater = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
60
60
  @bytesize = bytesize
61
61
  @buffer = nil
62
62
  end
@@ -10,7 +10,7 @@ module HTTPX
10
10
  #
11
11
  # It supports both *gzip* and *deflate*.
12
12
  #
13
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Compression
13
+ # https://gitlab.com/os85/httpx/wikis/Compression
14
14
  #
15
15
  module Compression
16
16
  class << self
@@ -30,7 +30,7 @@ module HTTPX
30
30
  module OptionsMethods
31
31
  def option_compression_threshold_size(value)
32
32
  bytes = Integer(value)
33
- raise TypeError, ":expect_threshold_size must be positive" unless bytes.positive?
33
+ raise TypeError, ":compression_threshold_size must be positive" unless bytes.positive?
34
34
 
35
35
  bytes
36
36
  end
@@ -138,7 +138,7 @@ module HTTPX
138
138
  def each(&blk)
139
139
  return enum_for(__method__) unless blk
140
140
 
141
- return deflate(&blk) if @buffer.size.zero?
141
+ return deflate(&blk) if @buffer.size.zero? # rubocop:disable Style/ZeroLengthPredicate
142
142
 
143
143
  @buffer.rewind
144
144
  @buffer.each(&blk)
@@ -152,7 +152,7 @@ module HTTPX
152
152
  private
153
153
 
154
154
  def deflate(&blk)
155
- return unless @buffer.size.zero?
155
+ return unless @buffer.size.zero? # rubocop:disable Style/ZeroLengthPredicate
156
156
 
157
157
  @body.rewind
158
158
  @deflater.deflate(@body, @buffer, chunk_size: 16_384, &blk)
@@ -9,7 +9,7 @@ module HTTPX
9
9
  #
10
10
  # It also adds a *#cookies* helper, so that you can pre-fill the cookies of a session.
11
11
  #
12
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Cookies
12
+ # https://gitlab.com/os85/httpx/wikis/Cookies
13
13
  #
14
14
  module Cookies
15
15
  def self.load_dependencies(*)
@@ -5,7 +5,7 @@ module HTTPX
5
5
  #
6
6
  # This plugin adds helper methods to implement HTTP Digest Auth (https://tools.ietf.org/html/rfc7616)
7
7
  #
8
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#authentication
8
+ # https://gitlab.com/os85/httpx/wikis/Authentication#authentication
9
9
  #
10
10
  module DigestAuth
11
11
  DigestError = Class.new(Error)
@@ -46,6 +46,8 @@ module HTTPX
46
46
 
47
47
  probe_response = wrap { super(request).first }
48
48
 
49
+ return probe_response unless probe_response.is_a?(Response)
50
+
49
51
  if probe_response.status == 401 && digest.can_authenticate?(probe_response.headers["www-authenticate"])
50
52
  request.transition(:idle)
51
53
  request.headers["authorization"] = digest.authenticate(request, probe_response.headers["www-authenticate"])
@@ -5,7 +5,7 @@ module HTTPX
5
5
  #
6
6
  # This plugin makes all HTTP/1.1 requests with a body send the "Expect: 100-continue".
7
7
  #
8
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Expect#expect
8
+ # https://gitlab.com/os85/httpx/wikis/Expect#expect
9
9
  #
10
10
  module Expect
11
11
  EXPECT_TIMEOUT = 2
@@ -50,7 +50,8 @@ module HTTPX
50
50
  end
51
51
 
52
52
  def response=(response)
53
- if response && response.status == 100 &&
53
+ if response.is_a?(Response) &&
54
+ response.status == 100 &&
54
55
  !@headers.key?("expect") &&
55
56
  (@state == :body || @state == :done)
56
57
 
@@ -92,7 +93,7 @@ module HTTPX
92
93
  response = @responses.delete(request)
93
94
  return unless response
94
95
 
95
- if response.status == 417 && request.headers.key?("expect")
96
+ if response.is_a?(Response) && response.status == 417 && request.headers.key?("expect")
96
97
  response.close
97
98
  request.headers.delete("expect")
98
99
  request.transition(:idle)
@@ -11,7 +11,7 @@ module HTTPX
11
11
  #
12
12
  # It also doesn't follow insecure redirects (https -> http) by default (see *follow_insecure_redirects*).
13
13
  #
14
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Follow-Redirects
14
+ # https://gitlab.com/os85/httpx/wikis/Follow-Redirects
15
15
  #
16
16
  module FollowRedirects
17
17
  MAX_REDIRECTS = 3
@@ -44,6 +44,7 @@ module HTTPX
44
44
 
45
45
  max_redirects = redirect_request.max_redirects
46
46
 
47
+ return response unless response.is_a?(Response)
47
48
  return response unless REDIRECT_STATUS.include?(response.status) && response.headers.key?("location")
48
49
  return response unless max_redirects.positive?
49
50
 
@@ -121,6 +122,12 @@ module HTTPX
121
122
  @redirect_request || self
122
123
  end
123
124
 
125
+ def response
126
+ return super unless @redirect_request
127
+
128
+ @redirect_request.response
129
+ end
130
+
124
131
  def max_redirects
125
132
  @options.max_redirects || MAX_REDIRECTS
126
133
  end
@@ -57,7 +57,7 @@ module HTTPX
57
57
 
58
58
  yield data
59
59
 
60
- message = message.byteslice((5 + size)..-1)
60
+ message = message.byteslice((size + 5)..-1)
61
61
  end
62
62
  end
63
63
 
@@ -16,7 +16,7 @@ module HTTPX
16
16
  #
17
17
  # This plugin adds DSL to build GRPC interfaces.
18
18
  #
19
- # https://gitlab.com/honeyryderchuck/httpx/wikis/GRPC
19
+ # https://gitlab.com/os85/httpx/wikis/GRPC
20
20
  #
21
21
  module GRPC
22
22
  unless String.method_defined?(:underscore)
@@ -6,7 +6,7 @@ module HTTPX
6
6
  # This plugin adds support for upgrading a plaintext HTTP/1.1 connection to HTTP/2
7
7
  # (https://tools.ietf.org/html/rfc7540#section-3.2)
8
8
  #
9
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Upgrade#h2c
9
+ # https://gitlab.com/os85/httpx/wikis/Upgrade#h2c
10
10
  #
11
11
  module H2C
12
12
  VALID_H2C_VERBS = %i[get options head].freeze
@@ -5,10 +5,6 @@ require "delegate"
5
5
 
6
6
  module HTTPX::Plugins
7
7
  module Multipart
8
- using HTTPX::RegexpExtensions unless Regexp.method_defined?(:match?)
9
-
10
- CRLF = "\r\n"
11
-
12
8
  class FilePart < SimpleDelegator
13
9
  attr_reader :original_filename, :content_type
14
10
 
@@ -20,32 +16,14 @@ module HTTPX::Plugins
20
16
  end
21
17
  end
22
18
 
23
- TOKEN = %r{[^\s()<>,;:\\"/\[\]?=]+}.freeze
24
- VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/.freeze
25
- CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i.freeze
26
- BROKEN_QUOTED = /^#{CONDISP}.*;\s*filename="(.*?)"(?:\s*$|\s*;\s*#{TOKEN}=)/i.freeze
27
- BROKEN_UNQUOTED = /^#{CONDISP}.*;\s*filename=(#{TOKEN})/i.freeze
28
- MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{CRLF}/ni.freeze
29
- MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*;\s*name=(#{VALUE})/ni.freeze
30
- MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{CRLF}]*)/ni.freeze
31
- # Updated definitions from RFC 2231
32
- ATTRIBUTE_CHAR = %r{[^ \t\v\n\r)(><@,;:\\"/\[\]?='*%]}.freeze
33
- ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/.freeze
34
- SECTION = /\*[0-9]+/.freeze
35
- REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/.freeze
36
- REGULAR_PARAMETER = /(#{REGULAR_PARAMETER_NAME})=(#{VALUE})/.freeze
37
- EXTENDED_OTHER_NAME = /#{ATTRIBUTE}\*[1-9][0-9]*\*/.freeze
38
- EXTENDED_OTHER_VALUE = /%[0-9a-fA-F]{2}|#{ATTRIBUTE_CHAR}/.freeze
39
- EXTENDED_OTHER_PARAMETER = /(#{EXTENDED_OTHER_NAME})=(#{EXTENDED_OTHER_VALUE}*)/.freeze
40
- EXTENDED_INITIAL_NAME = /#{ATTRIBUTE}(?:\*0)?\*/.freeze
41
- EXTENDED_INITIAL_VALUE = /[a-zA-Z0-9\-]*'[a-zA-Z0-9\-]*'#{EXTENDED_OTHER_VALUE}*/.freeze
42
- EXTENDED_INITIAL_PARAMETER = /(#{EXTENDED_INITIAL_NAME})=(#{EXTENDED_INITIAL_VALUE})/.freeze
43
- EXTENDED_PARAMETER = /#{EXTENDED_INITIAL_PARAMETER}|#{EXTENDED_OTHER_PARAMETER}/.freeze
44
- DISPPARM = /;\s*(?:#{REGULAR_PARAMETER}|#{EXTENDED_PARAMETER})\s*/.freeze
45
- RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i.freeze
46
-
47
19
  class Decoder
20
+ include HTTPX::Utils
21
+
22
+ CRLF = "\r\n"
48
23
  BOUNDARY_RE = /;\s*boundary=([^;]+)/i.freeze
24
+ MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{CRLF}/ni.freeze
25
+ MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:.*;\s*name=(#{VALUE})/ni.freeze
26
+ MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{CRLF}]*)/ni.freeze
49
27
  WINDOW_SIZE = 2 << 14
50
28
 
51
29
  def initialize(response)
@@ -102,7 +80,7 @@ module HTTPX::Plugins
102
80
  name = head[MULTIPART_CONTENT_ID, 1]
103
81
  end
104
82
 
105
- filename = get_filename(head)
83
+ filename = HTTPX::Utils.get_filename(head)
106
84
 
107
85
  name = filename || +"#{content_type || "text/plain"}[]" if name.nil? || name.empty?
108
86
 
@@ -154,34 +132,6 @@ module HTTPX::Plugins
154
132
  raise Error, "parsing should have been over by now"
155
133
  end until @buffer.empty?
156
134
  end
157
-
158
- def get_filename(head)
159
- filename = nil
160
- case head
161
- when RFC2183
162
- params = Hash[*head.scan(DISPPARM).flat_map(&:compact)]
163
-
164
- if (filename = params["filename"])
165
- filename = Regexp.last_match(1) if filename =~ /^"(.*)"$/
166
- elsif (filename = params["filename*"])
167
- encoding, _, filename = filename.split("'", 3)
168
- end
169
- when BROKEN_QUOTED, BROKEN_UNQUOTED
170
- filename = Regexp.last_match(1)
171
- end
172
-
173
- return unless filename
174
-
175
- filename = URI::DEFAULT_PARSER.unescape(filename) if filename.scan(/%.?.?/).all? { |s| /%[0-9a-fA-F]{2}/.match?(s) }
176
-
177
- filename.scrub!
178
-
179
- filename = filename.gsub(/\\(.)/, '\1') unless /\\[^\\"]/.match?(filename)
180
-
181
- filename.force_encoding ::Encoding.find(encoding) if encoding
182
-
183
- filename
184
- end
185
135
  end
186
136
  end
187
137
  end
@@ -7,7 +7,7 @@ module HTTPX
7
7
  #
8
8
  # HTTPX.post(URL, form: form: { image: HTTP::FormData::File.new("path/to/file")})
9
9
  #
10
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Multipart-Uploads
10
+ # https://gitlab.com/os85/httpx/wikis/Multipart-Uploads
11
11
  #
12
12
  module Multipart
13
13
  MULTIPART_VALUE_COND = lambda do |value|
@@ -29,7 +29,7 @@ module HTTPX
29
29
  # in order not to break legacy code, we'll keep loading http/form_data for them.
30
30
  require "http/form_data"
31
31
  warn "httpx: http/form_data is no longer a requirement to use HTTPX :multipart plugin. See migration instructions under" \
32
- "https://honeyryderchuck.gitlab.io/httpx/wiki/Multipart-Uploads.html#notes. \n\n" \
32
+ "https://os85.gitlab.io/httpx/wiki/Multipart-Uploads.html#notes. \n\n" \
33
33
  "If you'd like to stop seeing this message, require 'http/form_data' yourself."
34
34
  end
35
35
  rescue LoadError
@@ -3,7 +3,7 @@
3
3
  module HTTPX
4
4
  module Plugins
5
5
  #
6
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Authentication#ntlm-authentication
6
+ # https://gitlab.com/os85/httpx/wikis/Authentication#ntlm-authentication
7
7
  #
8
8
  module NTLMAuth
9
9
  class << self
@@ -39,6 +39,8 @@ module HTTPX
39
39
  request.headers["authorization"] = ntlm.negotiate
40
40
  probe_response = wrap { super(request).first }
41
41
 
42
+ return probe_response unless probe_response.is_a?(Response)
43
+
42
44
  if probe_response.status == 401 && ntlm.can_authenticate?(probe_response.headers["www-authenticate"])
43
45
  request.transition(:idle)
44
46
  request.headers["authorization"] = ntlm.authenticate(request, probe_response.headers["www-authenticate"])
@@ -15,7 +15,7 @@ module HTTPX
15
15
  # This plugin is also not recommendable when connecting to >9000 (like, a lot) different origins.
16
16
  # So when you use this, make sure that you don't fall into this trap.
17
17
  #
18
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Persistent
18
+ # https://gitlab.com/os85/httpx/wikis/Persistent
19
19
  #
20
20
  module Persistent
21
21
  def self.load_dependencies(klass)
@@ -23,6 +23,7 @@ module HTTPX
23
23
  response = super
24
24
 
25
25
  if response &&
26
+ response.is_a?(Response) &&
26
27
  response.status == 407 &&
27
28
  !request.headers.key?("proxy-authorization") &&
28
29
  response.headers.key?("proxy-authenticate")
@@ -113,13 +114,14 @@ module HTTPX
113
114
 
114
115
  def __http_on_connect(request, response)
115
116
  @inflight -= 1
116
- if response.status == 200
117
+ if response.is_a?(Response) && response.status == 200
117
118
  req = @pending.first
118
119
  request_uri = req.uri
119
120
  @io = ProxySSL.new(@io, request_uri, @options)
120
121
  transition(:connected)
121
122
  throw(:called)
122
- elsif response.status == 407 &&
123
+ elsif response.is_a?(Response) &&
124
+ response.status == 407 &&
123
125
  !request.headers.key?("proxy-authorization") &&
124
126
  @options.proxy.can_authenticate?(response.headers["proxy-authenticate"])
125
127
 
@@ -12,7 +12,7 @@ module HTTPX
12
12
  # * Socks4/4a proxies
13
13
  # * Socks5 proxies
14
14
  #
15
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Proxy
15
+ # https://gitlab.com/os85/httpx/wikis/Proxy
16
16
  #
17
17
  module Proxy
18
18
  Error = HTTPProxyError
@@ -8,7 +8,7 @@ module HTTPX
8
8
  # In order to benefit from this, requests are sent one at a time, so that
9
9
  # no push responses are received after corresponding request has been sent.
10
10
  #
11
- # https://gitlab.com/honeyryderchuck/httpx/wikis/Server-Push
11
+ # https://gitlab.com/os85/httpx/wikis/Server-Push
12
12
  #
13
13
  module PushPromise
14
14
  def self.extra_options(options)