excon 0.112.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a595b595665aaaf9b650c664bca78bdc66ad05b80d7641333ce3acbeb6a80c46
4
- data.tar.gz: 7200b150fded0987a7c57fb1155580efd0825472f375523ce12e2b0dce2ebf25
3
+ metadata.gz: 955c2ed7f6ee55d4a279f386f6041f2d465640bd2c49930fcb213f0e63852e17
4
+ data.tar.gz: 49190e08fa385b6bd878096da5df9ad062c8e643477930e60916908581c1ef02
5
5
  SHA512:
6
- metadata.gz: 27c315cb6b11bf5f09bdae2802d033cdee746d8d907c77324535452f03b42fe2f77375530761153062f5fc70f39972858e0dfe82d64edecc7e9ab83135ce93ba
7
- data.tar.gz: 9c37add84efa4abb2766310f27a4aa7a151e31cc9e53cfdbd321c3aade0909b88d6d9ee0c9dea3accba8761dbb356d6570eb099bf24a52a96ea0576c1217edd9
6
+ metadata.gz: d5fcebc27e76063b3be519a0eae585eabd4b3a40591fef96c1750cd7ddfcd9df940a760907f6f7717ab4628eb3f036640afe8da51312ec2741eb5eb8a13a612d
7
+ data.tar.gz: 10a234e21629066f1a6682c0c63a0f9bf60bd211ea13018ad5951c3012268e6826d88459d9bcee63518e2a3ccd1558dabb1fba03c9e7d450281d4ab7f8bc6c1a
data/README.md CHANGED
@@ -190,6 +190,9 @@ connection.request(:timeout => 0.1) # timeout if the entire request takes longer
190
190
  #
191
191
  connection = Excon.new('http://geemus.com/', :tcp_nodelay => true)
192
192
 
193
+ # opt-in to having Excon add a default port (http:80 and https:443)
194
+ connection = Excon.new('http://geemus.com/', :include_default_port => true)
195
+
193
196
  # set longer connect_timeout (default is 60 seconds)
194
197
  connection = Excon.new('http://geemus.com/', :connect_timeout => 360)
195
198
 
@@ -446,6 +446,12 @@ module Excon
446
446
  raise ArgumentError.new("Invalid validation type '#{validation}'")
447
447
  end
448
448
 
449
+ if validation == :connection && params[:omit_default_port] != true
450
+ Excon.display_warning(
451
+ 'The `omit_default_port` connection option is deprecated, please use `include_default_port` instead.'
452
+ )
453
+ end
454
+
449
455
  invalid_keys = params.keys - valid_keys
450
456
  unless invalid_keys.empty?
451
457
  Excon.display_warning("Invalid Excon #{validation} keys: #{invalid_keys.map(&:inspect).join(', ')}")
@@ -14,9 +14,11 @@ module Excon
14
14
  DEFAULT_RETRY_LIMIT = 4
15
15
 
16
16
  DEFAULT_RETRY_ERRORS = [
17
- Excon::Error::Timeout,
17
+ Excon::Error::RequestTimeout,
18
+ Excon::Error::Server,
18
19
  Excon::Error::Socket,
19
- Excon::Error::HTTPStatus
20
+ Excon::Error::Timeout,
21
+ Excon::Error::TooManyRequests
20
22
  ].freeze
21
23
 
22
24
  FORCE_ENC = CR_NL.respond_to?(:force_encoding)
@@ -84,6 +86,7 @@ module Excon
84
86
  keepalive
85
87
  host
86
88
  hostname
89
+ include_default_port
87
90
  omit_default_port
88
91
  nonblock
89
92
  reuseaddr
@@ -151,14 +154,16 @@ module Excon
151
154
  instrumentor_name: 'excon',
152
155
  middlewares: [
153
156
  Excon::Middleware::ResponseParser,
157
+ Excon::Middleware::Decompress,
154
158
  Excon::Middleware::Expects,
155
159
  Excon::Middleware::Idempotent,
156
160
  Excon::Middleware::Instrumentor,
157
161
  Excon::Middleware::Mock
158
162
  ],
159
163
  mock: false,
164
+ include_default_port: false,
160
165
  nonblock: true,
161
- omit_default_port: false,
166
+ omit_default_port: true,
162
167
  persistent: false,
163
168
  read_timeout: 60,
164
169
  resolv_resolver: nil,
@@ -1,41 +1,36 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Excon
3
4
  module Middleware
4
5
  class Decompress < Excon::Middleware::Base
5
-
6
6
  INFLATE_ZLIB_OR_GZIP = 47 # Zlib::MAX_WBITS + 32
7
7
  INFLATE_RAW = -15 # Zlib::MAX_WBITS * -1
8
8
 
9
9
  def request_call(datum)
10
- unless datum.has_key?(:response_block)
11
- key = datum[:headers].keys.detect {|k| k.to_s.casecmp('Accept-Encoding') == 0 } || 'Accept-Encoding'
12
- if datum[:headers][key].to_s.empty?
13
- datum[:headers][key] = 'deflate, gzip'
14
- end
10
+ unless datum.key?(:response_block)
11
+ key = datum[:headers].keys.detect { |k| k.to_s.casecmp('Accept-Encoding').zero? } || 'Accept-Encoding'
12
+ datum[:headers][key] = 'deflate, gzip' if datum[:headers][key].to_s.empty?
15
13
  end
16
14
  @stack.request_call(datum)
17
15
  end
18
16
 
19
17
  def response_call(datum)
20
18
  body = datum[:response][:body]
21
- unless datum.has_key?(:response_block) || body.nil? || body.empty?
22
- if (key = datum[:response][:headers].keys.detect {|k| k.casecmp('Content-Encoding') == 0 })
23
- encodings = Utils.split_header_value(datum[:response][:headers][key])
24
- if (encoding = encodings.last)
25
- if encoding.casecmp('deflate') == 0
26
- datum[:response][:body] = begin
27
- Zlib::Inflate.new(INFLATE_ZLIB_OR_GZIP).inflate(body)
28
- rescue Zlib::DataError # fallback to raw on error
29
- Zlib::Inflate.new(INFLATE_RAW).inflate(body)
30
- end
31
- encodings.pop
32
- elsif encoding.casecmp('gzip') == 0 || encoding.casecmp('x-gzip') == 0
33
- datum[:response][:body] = Zlib::GzipReader.new(StringIO.new(body)).read
34
- encodings.pop
35
- end
36
- datum[:response][:headers][key] = encodings.join(', ')
19
+ if !(datum.key?(:response_block) || body.nil? || body.empty?) &&
20
+ (key = datum[:response][:headers].keys.detect { |k| k.casecmp('Content-Encoding').zero? })
21
+ encodings = Utils.split_header_value(datum[:response][:headers][key])
22
+ if encodings.last.casecmp('deflate').zero?
23
+ datum[:response][:body] = begin
24
+ Zlib::Inflate.new(INFLATE_ZLIB_OR_GZIP).inflate(body)
25
+ rescue Zlib::DataError # fallback to raw on error
26
+ Zlib::Inflate.new(INFLATE_RAW).inflate(body)
37
27
  end
28
+ encodings.pop
29
+ elsif encodings.last.casecmp('gzip').zero? || encodings.last.casecmp('x-gzip').zero?
30
+ datum[:response][:body] = Zlib::GzipReader.new(StringIO.new(body)).read
31
+ encodings.pop
38
32
  end
33
+ datum[:response][:headers][key] = encodings.join(', ')
39
34
  end
40
35
  @stack.response_call(datum)
41
36
  end
@@ -108,7 +108,7 @@ module Excon
108
108
  end
109
109
 
110
110
  if @data[:proxy]
111
- request = "CONNECT #{@data[:host]}#{port_string(@data.merge(:omit_default_port => false))}#{Excon::HTTP_1_1}" +
111
+ request = "CONNECT #{@data[:host]}#{Excon::HTTP_1_1}" \
112
112
  "Host: #{@data[:host]}#{port_string(@data)}#{Excon::CR_NL}"
113
113
 
114
114
  if @data[:proxy].has_key?(:user) || @data[:proxy].has_key?(:password)
data/lib/excon/utils.rb CHANGED
@@ -62,11 +62,33 @@ module Excon
62
62
  end
63
63
 
64
64
  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
- ''
65
+ if !default_port?(datum) || datum[:include_default_port] || !datum[:omit_default_port]
66
+ ":#{datum[:port]}"
67
67
  else
68
- ':' + datum[:port].to_s
68
+ ''
69
+ end
70
+ end
71
+
72
+ # Used to normalize queries for stubs, based on Rack::Utils.parse_query
73
+ def parse_query_string(string)
74
+ params = {}
75
+
76
+ string.split(/[&;] */n).each do |pair|
77
+ key, value = pair.split('=', 2).map { |x| CGI.unescape(x) }
78
+
79
+ params[key] = if params[key]
80
+ [params[key], value].flatten
81
+ else
82
+ value
83
+ end
69
84
  end
85
+
86
+ params
87
+ end
88
+
89
+ def default_port?(datum)
90
+ (datum[:scheme].casecmp('http').zero? && datum[:port] == 80) ||
91
+ (datum[:scheme].casecmp('https').zero? && datum[:port] == 443)
70
92
  end
71
93
 
72
94
  def query_string(datum)
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.112.0'
4
+ VERSION = '1.0.0'
5
5
  end
data/lib/excon.rb CHANGED
@@ -19,6 +19,7 @@ require 'excon/version'
19
19
  require 'excon/extensions/uri'
20
20
 
21
21
  require 'excon/middlewares/base'
22
+ require 'excon/middlewares/decompress'
22
23
  require 'excon/middlewares/expects'
23
24
  require 'excon/middlewares/idempotent'
24
25
  require 'excon/middlewares/instrumentor'
@@ -32,7 +33,6 @@ require 'excon/utils'
32
33
  require 'excon/connection'
33
34
  require 'excon/headers'
34
35
  require 'excon/response'
35
- require 'excon/middlewares/decompress'
36
36
  require 'excon/middlewares/escape_path'
37
37
  require 'excon/middlewares/redirect_follower'
38
38
  require 'excon/middlewares/capture_cookies'
@@ -143,7 +143,7 @@ module Excon
143
143
  uri = URI.parse(url)
144
144
  request_params = {
145
145
  host: uri.host,
146
- path: uri.path,
146
+ path: uri.path.empty? ? '/' : uri.path,
147
147
  port: uri.port,
148
148
  query: uri.query,
149
149
  scheme: uri.scheme
@@ -162,6 +162,9 @@ module Excon
162
162
  end
163
163
  request_params[:headers] = headers
164
164
  end
165
+ if request_params.key?(:query) && request_params[:query].instance_of?(String)
166
+ request_params[:query] = Utils.parse_query_string(request_params[:query])
167
+ end
165
168
  if block_given?
166
169
  raise(ArgumentError, 'stub requires either response_params OR a block') if response_params
167
170
 
@@ -182,6 +185,9 @@ module Excon
182
185
  if (method = request_params.delete(:method))
183
186
  request_params[:method] = method.to_s.downcase.to_sym
184
187
  end
188
+ if request_params.key?(:query) && request_params[:query].instance_of?(String)
189
+ request_params[:query] = Utils.parse_query_string(request_params[:query])
190
+ end
185
191
  Excon.stubs.each do |stub, response_params|
186
192
  captures = { headers: {} }
187
193
  headers_match = !stub.key?(:headers) || stub[:headers].keys.all? do |key|
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.112.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dpiddy (Dan Peterson)
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-10-01 00:00:00.000000000 Z
13
+ date: 2024-10-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec