excon 0.90.0 → 0.99.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 +4 -4
- data/CONTRIBUTORS.md +182 -140
- data/README.md +84 -53
- data/data/cacert.pem +479 -339
- data/excon.gemspec +0 -1
- data/lib/excon/connection.rb +16 -1
- data/lib/excon/constants.rb +2 -0
- data/lib/excon/response.rb +13 -0
- data/lib/excon/socket.rb +41 -20
- data/lib/excon/ssl_socket.rb +17 -1
- data/lib/excon/version.rb +1 -1
- data/lib/excon.rb +14 -4
- metadata +6 -20
data/excon.gemspec
CHANGED
|
@@ -26,7 +26,6 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
s.add_development_dependency('eventmachine', '>= 1.0.4')
|
|
27
27
|
s.add_development_dependency('open4')
|
|
28
28
|
s.add_development_dependency('rake')
|
|
29
|
-
s.add_development_dependency('rdoc')
|
|
30
29
|
s.add_development_dependency('shindo')
|
|
31
30
|
s.add_development_dependency('sinatra')
|
|
32
31
|
s.add_development_dependency('sinatra-contrib')
|
data/lib/excon/connection.rb
CHANGED
|
@@ -62,6 +62,7 @@ module Excon
|
|
|
62
62
|
# @option params [Class] :instrumentor Responds to #instrument as in ActiveSupport::Notifications
|
|
63
63
|
# @option params [String] :instrumentor_name Name prefix for #instrument events. Defaults to 'excon'
|
|
64
64
|
def initialize(params = {})
|
|
65
|
+
@pid = Process.pid
|
|
65
66
|
@data = Excon.defaults.dup
|
|
66
67
|
# merge does not deep-dup, so make sure headers is not the original
|
|
67
68
|
@data[:headers] = @data[:headers].dup
|
|
@@ -89,7 +90,9 @@ module Excon
|
|
|
89
90
|
end
|
|
90
91
|
|
|
91
92
|
if @data[:scheme] == UNIX
|
|
92
|
-
|
|
93
|
+
# 'uri' >= v0.12.0 returns an empty string instead of nil for no host.
|
|
94
|
+
# So treat the parameter as present if and only if it is both non-nill and non-empty.
|
|
95
|
+
if @data[:host] && !@data[:host].empty?
|
|
93
96
|
raise ArgumentError, "The `:host` parameter should not be set for `unix://` connections.\n" +
|
|
94
97
|
"When supplying a `unix://` URI, it should start with `unix:/` or `unix:///`."
|
|
95
98
|
elsif !@data[:socket]
|
|
@@ -253,6 +256,11 @@ module Excon
|
|
|
253
256
|
datum[:headers] = { 'Host' => host }.merge(datum[:headers])
|
|
254
257
|
end
|
|
255
258
|
|
|
259
|
+
# default to GET if no method specified
|
|
260
|
+
unless datum[:method]
|
|
261
|
+
datum[:method] = :get
|
|
262
|
+
end
|
|
263
|
+
|
|
256
264
|
# if path is empty or doesn't start with '/', insert one
|
|
257
265
|
unless datum[:path][0, 1] == '/'
|
|
258
266
|
datum[:path] = datum[:path].dup.insert(0, '/')
|
|
@@ -473,6 +481,11 @@ module Excon
|
|
|
473
481
|
@_excon_sockets ||= {}
|
|
474
482
|
@_excon_sockets.compare_by_identity
|
|
475
483
|
|
|
484
|
+
if @pid != Process.pid
|
|
485
|
+
@_excon_sockets.clear # GC will take care of closing sockets
|
|
486
|
+
@pid = Process.pid
|
|
487
|
+
end
|
|
488
|
+
|
|
476
489
|
if @data[:thread_safe_sockets]
|
|
477
490
|
# In a multi-threaded world, if the same connection is used by multiple
|
|
478
491
|
# threads at the same time to connect to the same destination, they may
|
|
@@ -572,6 +585,8 @@ module Excon
|
|
|
572
585
|
raise ArgumentError, "The `:ssl_proxy_headers` parameter should only be used with HTTPS requests."
|
|
573
586
|
end
|
|
574
587
|
if @data[:proxy][:scheme] == UNIX
|
|
588
|
+
# URI.parse might return empty string for security reasons.
|
|
589
|
+
@data[:proxy][:host] = nil if @data[:proxy][:host] == ""
|
|
575
590
|
if @data[:proxy][:host]
|
|
576
591
|
raise ArgumentError, "The `:host` parameter should not be set for `unix://` proxies.\n" +
|
|
577
592
|
"When supplying a `unix://` URI, it should start with `unix:/` or `unix:///`."
|
data/lib/excon/constants.rb
CHANGED
data/lib/excon/response.rb
CHANGED
|
@@ -20,15 +20,24 @@ module Excon
|
|
|
20
20
|
def host
|
|
21
21
|
@data[:host]
|
|
22
22
|
end
|
|
23
|
+
def scheme
|
|
24
|
+
@data[:scheme]
|
|
25
|
+
end
|
|
23
26
|
def local_address
|
|
24
27
|
@data[:local_address]
|
|
25
28
|
end
|
|
26
29
|
def local_port
|
|
27
30
|
@data[:local_port]
|
|
28
31
|
end
|
|
32
|
+
def http_method # can't be named "method"
|
|
33
|
+
@data[:method]
|
|
34
|
+
end
|
|
29
35
|
def path
|
|
30
36
|
@data[:path]
|
|
31
37
|
end
|
|
38
|
+
def query
|
|
39
|
+
@data[:query]
|
|
40
|
+
end
|
|
32
41
|
def port
|
|
33
42
|
@data[:port]
|
|
34
43
|
end
|
|
@@ -72,9 +81,13 @@ module Excon
|
|
|
72
81
|
:body => String.new,
|
|
73
82
|
:cookies => [],
|
|
74
83
|
:host => datum[:host],
|
|
84
|
+
:scheme => datum[:scheme],
|
|
85
|
+
:method => datum[:method],
|
|
75
86
|
:headers => Excon::Headers.new,
|
|
76
87
|
:path => datum[:path],
|
|
88
|
+
:query => datum[:query],
|
|
77
89
|
:port => datum[:port],
|
|
90
|
+
:omit_default_port => datum[:omit_default_port],
|
|
78
91
|
:status => status,
|
|
79
92
|
:status_line => line,
|
|
80
93
|
:reason_phrase => reason_phrase
|
data/lib/excon/socket.rb
CHANGED
|
@@ -40,12 +40,14 @@ module Excon
|
|
|
40
40
|
|
|
41
41
|
def_delegators(:@socket, :close)
|
|
42
42
|
|
|
43
|
+
|
|
43
44
|
def initialize(data = {})
|
|
44
45
|
@data = data
|
|
45
46
|
@nonblock = data[:nonblock]
|
|
46
47
|
@port ||= @data[:port] || 80
|
|
47
48
|
@read_buffer = String.new
|
|
48
49
|
@eof = false
|
|
50
|
+
@backend_eof = false
|
|
49
51
|
connect
|
|
50
52
|
end
|
|
51
53
|
|
|
@@ -60,19 +62,31 @@ module Excon
|
|
|
60
62
|
end
|
|
61
63
|
|
|
62
64
|
def readline
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
if @nonblock && RUBY_VERSION.to_f > 1.8_7
|
|
66
|
+
result = String.new
|
|
67
|
+
block = @read_buffer
|
|
68
|
+
@read_buffer = String.new
|
|
69
|
+
|
|
70
|
+
loop do
|
|
71
|
+
idx = block.index("\n")
|
|
72
|
+
if idx.nil?
|
|
73
|
+
result << block
|
|
74
|
+
else
|
|
75
|
+
result << block.slice!(0, idx+1)
|
|
76
|
+
add_to_read_buffer(block)
|
|
77
|
+
break
|
|
78
|
+
end
|
|
79
|
+
block = read_nonblock(@data[:chunk_size]) || raise(EOFError)
|
|
80
|
+
end
|
|
81
|
+
result
|
|
82
|
+
else # nonblock/legacy
|
|
83
|
+
begin
|
|
84
|
+
Timeout.timeout(@data[:read_timeout]) do
|
|
85
|
+
@socket.readline
|
|
86
|
+
end
|
|
87
|
+
rescue Timeout::Error
|
|
88
|
+
raise Excon::Errors::Timeout.new('read timeout reached')
|
|
73
89
|
end
|
|
74
|
-
rescue Timeout::Error
|
|
75
|
-
raise Excon::Errors::Timeout.new('read timeout reached')
|
|
76
90
|
end
|
|
77
91
|
end
|
|
78
92
|
|
|
@@ -173,20 +187,27 @@ module Excon
|
|
|
173
187
|
end
|
|
174
188
|
end
|
|
175
189
|
|
|
190
|
+
def add_to_read_buffer(str)
|
|
191
|
+
@read_buffer << str
|
|
192
|
+
@eof = false
|
|
193
|
+
end
|
|
194
|
+
|
|
176
195
|
def read_nonblock(max_length)
|
|
177
196
|
begin
|
|
178
197
|
if max_length
|
|
179
|
-
until @read_buffer.length >= max_length
|
|
198
|
+
until @backend_eof || @read_buffer.length >= max_length
|
|
180
199
|
@read_buffer << @socket.read_nonblock(max_length - @read_buffer.length)
|
|
181
200
|
end
|
|
182
201
|
else
|
|
183
|
-
|
|
202
|
+
while !@backend_eof
|
|
184
203
|
@read_buffer << @socket.read_nonblock(@data[:chunk_size])
|
|
185
204
|
end
|
|
186
205
|
end
|
|
187
206
|
rescue OpenSSL::SSL::SSLError => error
|
|
188
207
|
if error.message == 'read would block'
|
|
189
|
-
|
|
208
|
+
if @read_buffer.empty?
|
|
209
|
+
select_with_timeout(@socket, :read) && retry
|
|
210
|
+
end
|
|
190
211
|
else
|
|
191
212
|
raise(error)
|
|
192
213
|
end
|
|
@@ -196,10 +217,10 @@ module Excon
|
|
|
196
217
|
select_with_timeout(@socket, :read) && retry
|
|
197
218
|
end
|
|
198
219
|
rescue EOFError
|
|
199
|
-
@
|
|
220
|
+
@backend_eof = true
|
|
200
221
|
end
|
|
201
222
|
|
|
202
|
-
if max_length
|
|
223
|
+
ret = if max_length
|
|
203
224
|
if @read_buffer.empty?
|
|
204
225
|
nil # EOF met at beginning
|
|
205
226
|
else
|
|
@@ -209,6 +230,8 @@ module Excon
|
|
|
209
230
|
# read until EOFError, so return everything
|
|
210
231
|
@read_buffer.slice!(0, @read_buffer.length)
|
|
211
232
|
end
|
|
233
|
+
@eof = @backend_eof && @read_buffer.empty?
|
|
234
|
+
ret
|
|
212
235
|
end
|
|
213
236
|
|
|
214
237
|
def read_block(max_length)
|
|
@@ -220,9 +243,7 @@ module Excon
|
|
|
220
243
|
raise(error)
|
|
221
244
|
end
|
|
222
245
|
rescue *READ_RETRY_EXCEPTION_CLASSES
|
|
223
|
-
|
|
224
|
-
select_with_timeout(@socket, :read) && retry
|
|
225
|
-
end
|
|
246
|
+
select_with_timeout(@socket, :read) && retry
|
|
226
247
|
rescue EOFError
|
|
227
248
|
@eof = true
|
|
228
249
|
end
|
data/lib/excon/ssl_socket.rb
CHANGED
|
@@ -90,6 +90,14 @@ module Excon
|
|
|
90
90
|
else
|
|
91
91
|
ssl_context.key = OpenSSL::PKey::RSA.new(client_key_data, client_key_pass)
|
|
92
92
|
end
|
|
93
|
+
if client_chain_data && OpenSSL::X509::Certificate.respond_to?(:load)
|
|
94
|
+
ssl_context.extra_chain_cert = OpenSSL::X509::Certificate.load(client_chain_data)
|
|
95
|
+
elsif client_chain_data
|
|
96
|
+
certs = client_chain_data.scan(/-----BEGIN CERTIFICATE-----(?:.|\n)+?-----END CERTIFICATE-----/)
|
|
97
|
+
ssl_context.extra_chain_cert = certs.map do |cert|
|
|
98
|
+
OpenSSL::X509::Certificate.new(cert)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
93
101
|
elsif @data.key?(:certificate) && @data.key?(:private_key)
|
|
94
102
|
ssl_context.cert = OpenSSL::X509::Certificate.new(@data[:certificate])
|
|
95
103
|
if OpenSSL::PKey.respond_to? :read
|
|
@@ -133,7 +141,7 @@ module Excon
|
|
|
133
141
|
|
|
134
142
|
# Server Name Indication (SNI) RFC 3546
|
|
135
143
|
if @socket.respond_to?(:hostname=)
|
|
136
|
-
@socket.hostname = @data[:host]
|
|
144
|
+
@socket.hostname = @data[:ssl_verify_peer_host] || @data[:host]
|
|
137
145
|
end
|
|
138
146
|
|
|
139
147
|
begin
|
|
@@ -171,6 +179,14 @@ module Excon
|
|
|
171
179
|
end
|
|
172
180
|
end
|
|
173
181
|
|
|
182
|
+
def client_chain_data
|
|
183
|
+
@client_chain_data ||= if (ccd = @data[:client_chain_data])
|
|
184
|
+
ccd
|
|
185
|
+
elsif (path = @data[:client_chain])
|
|
186
|
+
File.read path
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
174
190
|
def connect
|
|
175
191
|
# backwards compatability for things lacking nonblock
|
|
176
192
|
@nonblock = HAVE_NONBLOCK && @nonblock
|
data/lib/excon/version.rb
CHANGED
data/lib/excon.rb
CHANGED
|
@@ -198,8 +198,13 @@ module Excon
|
|
|
198
198
|
headers_match = !stub.has_key?(:headers) || stub[:headers].keys.all? do |key|
|
|
199
199
|
case value = stub[:headers][key]
|
|
200
200
|
when Regexp
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
case request_params[:headers][key]
|
|
202
|
+
when String
|
|
203
|
+
if (match = value.match(request_params[:headers][key]))
|
|
204
|
+
captures[:headers][key] = match.captures
|
|
205
|
+
end
|
|
206
|
+
when Regexp # for unstub on regex params
|
|
207
|
+
match = (value == request_params[:headers][key])
|
|
203
208
|
end
|
|
204
209
|
match
|
|
205
210
|
else
|
|
@@ -209,8 +214,13 @@ module Excon
|
|
|
209
214
|
non_headers_match = (stub.keys - [:headers]).all? do |key|
|
|
210
215
|
case value = stub[key]
|
|
211
216
|
when Regexp
|
|
212
|
-
|
|
213
|
-
|
|
217
|
+
case request_params[key]
|
|
218
|
+
when String
|
|
219
|
+
if (match = value.match(request_params[key]))
|
|
220
|
+
captures[key] = match.captures
|
|
221
|
+
end
|
|
222
|
+
when Regexp # for unstub on regex params
|
|
223
|
+
match = (value == request_params[key])
|
|
214
224
|
end
|
|
215
225
|
match
|
|
216
226
|
else
|
metadata
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: excon
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.99.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dpiddy (Dan Peterson)
|
|
8
8
|
- geemus (Wesley Beary)
|
|
9
9
|
- nextmat (Matt Sanders)
|
|
10
|
-
autorequire:
|
|
10
|
+
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2023-02-03 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: rspec
|
|
@@ -96,20 +96,6 @@ dependencies:
|
|
|
96
96
|
- - ">="
|
|
97
97
|
- !ruby/object:Gem::Version
|
|
98
98
|
version: '0'
|
|
99
|
-
- !ruby/object:Gem::Dependency
|
|
100
|
-
name: rdoc
|
|
101
|
-
requirement: !ruby/object:Gem::Requirement
|
|
102
|
-
requirements:
|
|
103
|
-
- - ">="
|
|
104
|
-
- !ruby/object:Gem::Version
|
|
105
|
-
version: '0'
|
|
106
|
-
type: :development
|
|
107
|
-
prerelease: false
|
|
108
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
109
|
-
requirements:
|
|
110
|
-
- - ">="
|
|
111
|
-
- !ruby/object:Gem::Version
|
|
112
|
-
version: '0'
|
|
113
99
|
- !ruby/object:Gem::Dependency
|
|
114
100
|
name: shindo
|
|
115
101
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -249,7 +235,7 @@ metadata:
|
|
|
249
235
|
documentation_uri: https://github.com/excon/excon/blob/master/README.md
|
|
250
236
|
source_code_uri: https://github.com/excon/excon
|
|
251
237
|
wiki_uri: https://github.com/excon/excon/wiki
|
|
252
|
-
post_install_message:
|
|
238
|
+
post_install_message:
|
|
253
239
|
rdoc_options:
|
|
254
240
|
- "--charset=UTF-8"
|
|
255
241
|
require_paths:
|
|
@@ -265,8 +251,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
265
251
|
- !ruby/object:Gem::Version
|
|
266
252
|
version: '0'
|
|
267
253
|
requirements: []
|
|
268
|
-
rubygems_version: 3.
|
|
269
|
-
signing_key:
|
|
254
|
+
rubygems_version: 3.4.1
|
|
255
|
+
signing_key:
|
|
270
256
|
specification_version: 4
|
|
271
257
|
summary: speed, persistence, http(s)
|
|
272
258
|
test_files: []
|