excon 0.110.0 → 1.2.7

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.
@@ -13,11 +13,6 @@ module Excon
13
13
 
14
14
  # Methods that must be implemented by a plugin
15
15
  INSTANCE_REQUIRES = [:start]
16
- Excon.defaults.merge!(
17
- connect_timeout: 5,
18
- read_timeout: 5,
19
- write_timeout: 5
20
- )
21
16
 
22
17
  def initialize(args)
23
18
  # TODO: Validate these args
@@ -55,7 +50,7 @@ module Excon
55
50
  if RUBY_PLATFORM == 'java'
56
51
  Process.kill('USR1', pid)
57
52
  else
58
- Process.kill(9, pid)
53
+ Process.kill('KILL', pid)
59
54
  Process.wait(pid)
60
55
  end
61
56
 
@@ -73,7 +68,7 @@ module Excon
73
68
  while (line = lines.shift)
74
69
  case line
75
70
  when /(ERROR|Error)/
76
- unless line =~ /(null cert chain|did not return a certificate|SSL_read:: internal error)/
71
+ unless line.match?(/(null cert chain|did not return a certificate|SSL_read:: internal error)/)
77
72
  in_err = true
78
73
  puts
79
74
  end
@@ -34,7 +34,7 @@ module Excon
34
34
  end
35
35
 
36
36
  rescue => error
37
- @socket.close rescue nil if @socket
37
+ @socket&.close rescue nil
38
38
  raise error
39
39
  end
40
40
 
data/lib/excon/utils.rb CHANGED
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Excon
3
4
  module Utils
4
- extend self
5
+ module_function
5
6
 
6
- CONTROL = (0x0..0x1f).map {|c| c.chr }.join + "\x7f"
7
+ CONTROL = "#{(0x0..0x1f).map(&:chr).join}\u007F"
7
8
  DELIMS = '<>#%"'
8
9
  UNWISE = '{}|\\^[]`'
9
- NONASCII = (0x80..0xff).map {|c| c.chr }.join
10
- UNESCAPED = /([#{ Regexp.escape(CONTROL + ' ' + DELIMS + UNWISE + NONASCII) }])/
11
- ESCAPED = /%([0-9a-fA-F]{2})/
10
+ NONASCII = (0x80..0xff).map(&:chr).join
11
+ UNESCAPED = /([#{Regexp.escape("#{CONTROL} #{DELIMS}#{UNWISE}#{NONASCII}")}])/.freeze
12
+ ESCAPED = /%([0-9a-fA-F]{2})/.freeze
12
13
 
13
14
  def binary_encode(string)
14
15
  if FORCE_ENC && string.encoding != Encoding::ASCII_8BIT
@@ -23,9 +24,8 @@ module Excon
23
24
  end
24
25
 
25
26
  def connection_uri(datum = @data)
26
- unless datum
27
- raise ArgumentError, '`datum` must be given unless called on a Connection'
28
- end
27
+ raise ArgumentError, '`datum` must be given unless called on a Connection' unless datum
28
+
29
29
  if datum[:scheme] == UNIX
30
30
  "#{datum[:scheme]}://#{datum[:socket]}"
31
31
  else
@@ -36,21 +36,15 @@ module Excon
36
36
  # Redact sensitive info from provided data
37
37
  def redact(datum)
38
38
  datum = datum.dup
39
- if datum.has_key?(:headers)
40
- if datum[:headers].has_key?('Authorization') || datum[:headers].has_key?('Proxy-Authorization')
39
+ if datum.key?(:headers)
40
+ if datum[:headers].key?('Authorization') || datum[:headers].key?('Proxy-Authorization')
41
41
  datum[:headers] = datum[:headers].dup
42
42
  end
43
- if datum[:headers].has_key?('Authorization')
44
- datum[:headers]['Authorization'] = REDACTED
45
- end
46
- if datum[:headers].has_key?('Proxy-Authorization')
47
- datum[:headers]['Proxy-Authorization'] = REDACTED
48
- end
49
- end
50
- if datum.has_key?(:password)
51
- datum[:password] = REDACTED
43
+ datum[:headers]['Authorization'] = REDACTED if datum[:headers].key?('Authorization')
44
+ datum[:headers]['Proxy-Authorization'] = REDACTED if datum[:headers].key?('Proxy-Authorization')
52
45
  end
53
- if datum.has_key?(:proxy) && datum[:proxy] && datum[:proxy].has_key?(:password)
46
+ datum[:password] = REDACTED if datum.key?(:password)
47
+ if datum.key?(:proxy) && datum[:proxy]&.key?(:password)
54
48
  datum[:proxy] = datum[:proxy].dup
55
49
  datum[:proxy][:password] = REDACTED
56
50
  end
@@ -62,21 +56,27 @@ module Excon
62
56
  end
63
57
 
64
58
  def port_string(datum)
65
- if datum[:port].nil? || (datum[:omit_default_port] && ((datum[:scheme].casecmp('http') == 0 && datum[:port] == 80) || (datum[:scheme].casecmp('https') == 0 && datum[:port] == 443)))
66
- ''
59
+ if !default_port?(datum) || datum[:include_default_port] || !datum[:omit_default_port]
60
+ ":#{datum[:port]}"
67
61
  else
68
- ':' + datum[:port].to_s
62
+ ''
69
63
  end
70
64
  end
71
65
 
66
+ def default_port?(datum)
67
+ (!datum[:scheme]&.casecmp?('unix') && datum[:port].nil?) ||
68
+ (datum[:scheme]&.casecmp?('http') && datum[:port] == 80) ||
69
+ (datum[:scheme]&.casecmp?('https') && datum[:port] == 443)
70
+ end
71
+
72
72
  def query_string(datum)
73
- str = String.new
73
+ str = +''
74
74
  case datum[:query]
75
75
  when String
76
76
  str << '?' << datum[:query]
77
77
  when Hash
78
78
  str << '?'
79
- datum[:query].sort_by {|k,_| k.to_s }.each do |key, values|
79
+ datum[:query].sort_by { |k, _| k.to_s }.each do |key, values|
80
80
  key = CGI.escape(key.to_s)
81
81
  if values.nil?
82
82
  str << key << '&'
@@ -94,46 +94,49 @@ module Excon
94
94
  # Splits a header value +str+ according to HTTP specification.
95
95
  def split_header_value(str)
96
96
  return [] if str.nil?
97
+
97
98
  str = str.dup.strip
98
99
  str = binary_encode(str)
99
- str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",])+)
100
- (?:,\s*|\Z)'xn).flatten
100
+ str.scan(/\G((?:"(?:\\.|[^"])+?"|[^",])+)
101
+ (?:,\s*|\Z)/xn).flatten
101
102
  end
102
103
 
103
104
  # Escapes HTTP reserved and unwise characters in +str+
104
105
  def escape_uri(str)
105
106
  str = str.dup
106
107
  str = binary_encode(str)
107
- str.gsub(UNESCAPED) { "%%%02X" % $1[0].ord }
108
+ str.gsub(UNESCAPED) { format('%%%02X', ::Regexp.last_match(1)[0].ord) }
108
109
  end
109
110
 
110
111
  # Unescapes HTTP reserved and unwise characters in +str+
111
112
  def unescape_uri(str)
112
113
  str = str.dup
113
114
  str = binary_encode(str)
114
- str.gsub(ESCAPED) { $1.hex.chr }
115
+ str.gsub(ESCAPED) { ::Regexp.last_match(1).hex.chr }
115
116
  end
116
117
 
117
118
  # Unescape form encoded values in +str+
118
119
  def unescape_form(str)
119
120
  str = str.dup
120
121
  str = binary_encode(str)
121
- str.gsub!(/\+/, ' ')
122
- str.gsub(ESCAPED) { $1.hex.chr }
122
+ str.tr!('+', ' ')
123
+ str.gsub(ESCAPED) { ::Regexp.last_match(1).hex.chr }
123
124
  end
124
125
 
125
126
  # Performs validation on the passed header hash and returns a string representation of the headers
126
127
  def headers_hash_to_s(headers)
127
- headers_str = String.new
128
+ headers_str = +''
128
129
  headers.each do |key, values|
129
- if key.to_s.match(/[\r\n]/)
130
- raise Excon::Errors::InvalidHeaderKey.new(key.to_s.inspect + ' contains forbidden "\r" or "\n"')
130
+ if key.to_s.match?(/[\r\n]/)
131
+ raise Excon::Errors::InvalidHeaderKey, "#{key.to_s.inspect} contains forbidden \"\\r\" or \"\\n\""
131
132
  end
133
+
132
134
  [values].flatten.each do |value|
133
- if value.to_s.match(/[\r\n]/)
135
+ if value.to_s.match?(/[\r\n]/)
134
136
  # Don't include the potentially sensitive header value (i.e. authorization token) in the message
135
- raise Excon::Errors::InvalidHeaderValue.new(key.to_s + ' header value contains forbidden "\r" or "\n"')
137
+ raise Excon::Errors::InvalidHeaderValue, "#{key} header value contains forbidden \"\\r\" or \"\\n\""
136
138
  end
139
+
137
140
  headers_str << key.to_s << ': ' << value.to_s << CR_NL
138
141
  end
139
142
  end
data/lib/excon/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Excon
4
- VERSION = '0.110.0'
4
+ VERSION = '1.2.7'
5
5
  end
data/lib/excon.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  $:.unshift(File.dirname(__FILE__)) unless
3
4
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
5
 
5
6
  require 'cgi'
6
7
  require 'forwardable'
8
+ require 'ipaddr'
7
9
  require 'openssl'
8
10
  require 'rbconfig'
9
11
  require 'socket'
@@ -17,6 +19,7 @@ require 'excon/version'
17
19
  require 'excon/extensions/uri'
18
20
 
19
21
  require 'excon/middlewares/base'
22
+ require 'excon/middlewares/decompress'
20
23
  require 'excon/middlewares/expects'
21
24
  require 'excon/middlewares/idempotent'
22
25
  require 'excon/middlewares/instrumentor'
@@ -30,7 +33,6 @@ require 'excon/utils'
30
33
  require 'excon/connection'
31
34
  require 'excon/headers'
32
35
  require 'excon/response'
33
- require 'excon/middlewares/decompress'
34
36
  require 'excon/middlewares/escape_path'
35
37
  require 'excon/middlewares/redirect_follower'
36
38
  require 'excon/middlewares/capture_cookies'
@@ -44,27 +46,22 @@ require 'excon/unix_socket'
44
46
  # Define defaults first so they will be available to other files
45
47
  module Excon
46
48
  class << self
47
-
48
49
  # @return [Hash] defaults for Excon connections
49
50
  def defaults
50
- @defaults ||= DEFAULTS
51
+ @defaults ||= DEFAULTS.dup
51
52
  end
52
53
 
53
54
  # Change defaults for Excon connections
54
55
  # @return [Hash] defaults for Excon connections
55
- def defaults=(new_defaults)
56
- @defaults = new_defaults
57
- end
56
+ attr_writer :defaults
58
57
 
59
58
  def display_warning(warning)
60
59
  # Show warning if $VERBOSE or ENV['EXCON_DEBUG'] is set
61
- if $VERBOSE || ENV['EXCON_DEBUG']
62
- $stderr.puts "[excon][WARNING] #{warning}\n#{ caller.join("\n") }"
63
- end
60
+ ($VERBOSE || ENV['EXCON_DEBUG']) && Warning.warn("[excon][WARNING] #{warning}\n#{caller.join("\n")}")
64
61
 
65
- if @raise_on_warnings
66
- raise Error::Warning.new(warning)
67
- end
62
+ return unless @raise_on_warnings
63
+
64
+ raise(Error::Warning, warning)
68
65
  end
69
66
 
70
67
  def set_raise_on_warnings!(should_raise)
@@ -119,32 +116,25 @@ module Excon
119
116
  def new(url, params = {})
120
117
  uri_parser = params[:uri_parser] || defaults[:uri_parser]
121
118
  uri = uri_parser.parse(url)
122
- if params[:path]
123
- uri_parser.parse(params[:path])
124
- end
125
- unless uri.scheme
126
- raise ArgumentError.new("Invalid URI: #{uri}")
127
- end
119
+ params[:path] && uri_parser.parse(params[:path])
120
+ raise(ArgumentError, "Invalid URI: #{uri}") unless uri.scheme
121
+
128
122
  params = {
129
- :host => uri.host,
130
- :hostname => uri.hostname,
131
- :path => uri.path,
132
- :port => uri.port,
133
- :query => uri.query,
134
- :scheme => uri.scheme
123
+ host: uri.host,
124
+ hostname: uri.hostname,
125
+ path: uri.path,
126
+ port: uri.port,
127
+ query: uri.query,
128
+ scheme: uri.scheme
135
129
  }.merge(params)
136
- if uri.password
137
- params[:password] = Utils.unescape_uri(uri.password)
138
- end
139
- if uri.user
140
- params[:user] = Utils.unescape_uri(uri.user)
141
- end
130
+ uri.password && params[:password] = Utils.unescape_uri(uri.password)
131
+ uri.user && params[:user] = Utils.unescape_uri(uri.user)
142
132
  Excon::Connection.new(params)
143
133
  end
144
134
 
145
135
  # push an additional stub onto the list to check for mock requests
146
136
  # @param request_params [Hash<Symbol, >] request params to match against, omitted params match all
147
- # @param response_params [Hash<Symbol, >] response params to return from matched request or block to call with params
137
+ # @param response_params [Hash<Symbol, >] response params to return or block to call with matched params
148
138
  def stub(request_params = {}, response_params = nil, &block)
149
139
  if (method = request_params.delete(:method))
150
140
  request_params[:method] = method.to_s.downcase.to_sym
@@ -152,35 +142,35 @@ module Excon
152
142
  if (url = request_params.delete(:url))
153
143
  uri = URI.parse(url)
154
144
  request_params = {
155
- :host => uri.host,
156
- :path => uri.path,
157
- :port => uri.port,
158
- :query => uri.query,
159
- :scheme => uri.scheme
145
+ host: uri.host,
146
+ path: uri.path.empty? ? '/' : uri.path,
147
+ port: uri.port,
148
+ query: uri.query,
149
+ scheme: uri.scheme
160
150
  }.merge!(request_params)
161
151
  if uri.user || uri.password
162
152
  request_params[:headers] ||= {}
163
- user, pass = Utils.unescape_form(uri.user.to_s), Utils.unescape_form(uri.password.to_s)
153
+ user = Utils.unescape_form(uri.user.to_s)
154
+ pass = Utils.unescape_form(uri.password.to_s)
164
155
  request_params[:headers]['Authorization'] ||= 'Basic ' + ["#{user}:#{pass}"].pack('m').delete(Excon::CR_NL)
165
156
  end
166
157
  end
167
- if request_params.has_key?(:headers)
158
+ if request_params.key?(:headers)
168
159
  headers = Excon::Headers.new
169
160
  request_params[:headers].each do |key, value|
170
161
  headers[key] = value
171
162
  end
172
163
  request_params[:headers] = headers
173
164
  end
165
+ request_params[:query] = Utils.query_string(request_params)[1...] if request_params.key?(:query)
174
166
  if block_given?
175
- if response_params
176
- raise(ArgumentError.new("stub requires either response_params OR a block"))
177
- else
178
- stub = [request_params, block]
179
- end
167
+ raise(ArgumentError, 'stub requires either response_params OR a block') if response_params
168
+
169
+ stub = [request_params, block]
180
170
  elsif response_params
181
171
  stub = [request_params, response_params]
182
172
  else
183
- raise(ArgumentError.new("stub requires either response_params OR a block"))
173
+ raise(ArgumentError, 'stub requires either response_params OR a block')
184
174
  end
185
175
  stubs.unshift(stub)
186
176
  stub
@@ -193,9 +183,10 @@ module Excon
193
183
  if (method = request_params.delete(:method))
194
184
  request_params[:method] = method.to_s.downcase.to_sym
195
185
  end
186
+ request_params[:query] = Utils.query_string(request_params)[1...] if request_params.key?(:query)
196
187
  Excon.stubs.each do |stub, response_params|
197
- captures = { :headers => {} }
198
- headers_match = !stub.has_key?(:headers) || stub[:headers].keys.all? do |key|
188
+ captures = { headers: {} }
189
+ headers_match = !stub.key?(:headers) || stub[:headers].keys.all? do |key|
199
190
  case value = stub[:headers][key]
200
191
  when Regexp
201
192
  case request_params[:headers][key]
@@ -249,9 +240,9 @@ module Excon
249
240
  # @param request_params [Hash<Symbol, >] request params to match against, omitted params match all
250
241
  # @return [Hash<Symbol, >] response params from deleted stub
251
242
  def unstub(request_params = {})
252
- if (stub = stub_for(request_params))
253
- Excon.stubs.delete_at(Excon.stubs.index(stub))
254
- end
243
+ return unless (stub = stub_for(request_params))
244
+
245
+ Excon.stubs.delete_at(Excon.stubs.index(stub))
255
246
  end
256
247
 
257
248
  # Generic non-persistent HTTP methods
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: excon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.110.0
4
+ version: 1.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - dpiddy (Dan Peterson)
@@ -10,22 +10,22 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-03-12 00:00:00.000000000 Z
13
+ date: 2025-05-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: rspec
16
+ name: logger
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: 3.5.0
22
- type: :development
21
+ version: '0'
22
+ type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: 3.5.0
28
+ version: '0'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: activesupport
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -68,6 +68,20 @@ dependencies:
68
68
  - - ">="
69
69
  - !ruby/object:Gem::Version
70
70
  version: 1.0.4
71
+ - !ruby/object:Gem::Dependency
72
+ name: json
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 1.8.5
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 1.8.5
71
85
  - !ruby/object:Gem::Dependency
72
86
  name: open4
73
87
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +97,7 @@ dependencies:
83
97
  - !ruby/object:Gem::Version
84
98
  version: '0'
85
99
  - !ruby/object:Gem::Dependency
86
- name: rake
100
+ name: puma
87
101
  requirement: !ruby/object:Gem::Requirement
88
102
  requirements:
89
103
  - - ">="
@@ -97,7 +111,7 @@ dependencies:
97
111
  - !ruby/object:Gem::Version
98
112
  version: '0'
99
113
  - !ruby/object:Gem::Dependency
100
- name: shindo
114
+ name: rake
101
115
  requirement: !ruby/object:Gem::Requirement
102
116
  requirements:
103
117
  - - ">="
@@ -111,7 +125,7 @@ dependencies:
111
125
  - !ruby/object:Gem::Version
112
126
  version: '0'
113
127
  - !ruby/object:Gem::Dependency
114
- name: sinatra
128
+ name: rdoc
115
129
  requirement: !ruby/object:Gem::Requirement
116
130
  requirements:
117
131
  - - ">="
@@ -125,7 +139,21 @@ dependencies:
125
139
  - !ruby/object:Gem::Version
126
140
  version: '0'
127
141
  - !ruby/object:Gem::Dependency
128
- name: sinatra-contrib
142
+ name: rspec
143
+ requirement: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: 3.5.0
148
+ type: :development
149
+ prerelease: false
150
+ version_requirements: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 3.5.0
155
+ - !ruby/object:Gem::Dependency
156
+ name: shindo
129
157
  requirement: !ruby/object:Gem::Requirement
130
158
  requirements:
131
159
  - - ">="
@@ -139,21 +167,21 @@ dependencies:
139
167
  - !ruby/object:Gem::Version
140
168
  version: '0'
141
169
  - !ruby/object:Gem::Dependency
142
- name: json
170
+ name: sinatra
143
171
  requirement: !ruby/object:Gem::Requirement
144
172
  requirements:
145
173
  - - ">="
146
174
  - !ruby/object:Gem::Version
147
- version: 1.8.5
175
+ version: '0'
148
176
  type: :development
149
177
  prerelease: false
150
178
  version_requirements: !ruby/object:Gem::Requirement
151
179
  requirements:
152
180
  - - ">="
153
181
  - !ruby/object:Gem::Version
154
- version: 1.8.5
182
+ version: '0'
155
183
  - !ruby/object:Gem::Dependency
156
- name: puma
184
+ name: sinatra-contrib
157
185
  requirement: !ruby/object:Gem::Requirement
158
186
  requirements:
159
187
  - - ">="
@@ -229,10 +257,11 @@ homepage: https://github.com/excon/excon
229
257
  licenses:
230
258
  - MIT
231
259
  metadata:
232
- homepage_uri: https://github.com/excon/excon
233
260
  bug_tracker_uri: https://github.com/excon/excon/issues
234
261
  changelog_uri: https://github.com/excon/excon/blob/master/changelog.txt
235
262
  documentation_uri: https://github.com/excon/excon/blob/master/README.md
263
+ funding_uri: https://github.com/sponsors/geemus
264
+ homepage_uri: https://github.com/excon/excon
236
265
  source_code_uri: https://github.com/excon/excon
237
266
  wiki_uri: https://github.com/excon/excon/wiki
238
267
  post_install_message:
@@ -244,14 +273,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
244
273
  requirements:
245
274
  - - ">="
246
275
  - !ruby/object:Gem::Version
247
- version: 2.7.0
276
+ version: 3.1.0
248
277
  required_rubygems_version: !ruby/object:Gem::Requirement
249
278
  requirements:
250
279
  - - ">="
251
280
  - !ruby/object:Gem::Version
252
281
  version: '0'
253
282
  requirements: []
254
- rubygems_version: 3.4.22
283
+ rubygems_version: 3.5.18
255
284
  signing_key:
256
285
  specification_version: 4
257
286
  summary: speed, persistence, http(s)