excon 0.7.8 → 0.7.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of excon might be problematic. Click here for more details.
- data/excon.gemspec +3 -3
- data/lib/excon/connection.rb +10 -1
- data/lib/excon/constants.rb +5 -2
- data/lib/excon/socket.rb +37 -17
- data/lib/excon/ssl_socket.rb +1 -1
- data/tests/idempotent_tests.rb +89 -1
- data/tests/request_method_tests.rb +3 -3
- data/tests/test_helper.rb +2 -0
- metadata +32 -17
data/excon.gemspec
CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
|
|
13
13
|
## If your rubyforge_project name is different, then edit it and comment out
|
14
14
|
## the sub! line in the Rakefile
|
15
15
|
s.name = 'excon'
|
16
|
-
s.version = '0.7.
|
17
|
-
s.date = '2011-11-
|
16
|
+
s.version = '0.7.9'
|
17
|
+
s.date = '2011-11-30'
|
18
18
|
s.rubyforge_project = 'excon'
|
19
19
|
|
20
20
|
## Make sure your summary is short. The description may be as long
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
## List the primary authors. If there are a bunch of authors, it's probably
|
26
26
|
## better to set the email to an email list or something. If you don't have
|
27
27
|
## a custom homepage, consider using your GitHub URL or the like.
|
28
|
-
s.authors = ["geemus (Wesley Beary)"]
|
28
|
+
s.authors = ["dpiddy (Dan Peterson)", "geemus (Wesley Beary)", "nextmat (Matt Sanders)"]
|
29
29
|
s.email = 'geemus@gmail.com'
|
30
30
|
s.homepage = 'https://github.com/geemus/excon'
|
31
31
|
|
data/lib/excon/connection.rb
CHANGED
@@ -17,6 +17,7 @@ module Excon
|
|
17
17
|
# @option params [Hash] :query Default query; appended to the 'scheme://host:port/path/' in the form of '?key=value'. Will only be used if params[:query] is not supplied to Connection#request
|
18
18
|
# @option params [String] :scheme The protocol; 'https' causes OpenSSL to be used
|
19
19
|
# @option params [String] :proxy Proxy server; e.g. 'http://myproxy.com:8888'
|
20
|
+
# @option params [Fixnum] :retry_limit Set how many times we'll retry a failed request. (Default 4)
|
20
21
|
def initialize(url, params = {})
|
21
22
|
uri = URI.parse(url)
|
22
23
|
@connection = {
|
@@ -39,6 +40,8 @@ module Excon
|
|
39
40
|
@proxy = setup_proxy(params[:proxy])
|
40
41
|
end
|
41
42
|
|
43
|
+
self.retry_limit = params[:retry_limit] || DEFAULT_RETRY_LIMIT
|
44
|
+
|
42
45
|
if @connection[:scheme] == 'https'
|
43
46
|
# use https_proxy if that has been specified
|
44
47
|
if ENV.has_key?('https_proxy')
|
@@ -198,7 +201,7 @@ module Excon
|
|
198
201
|
|
199
202
|
rescue => request_error
|
200
203
|
if params[:idempotent] && [Excon::Errors::SocketError, Excon::Errors::HTTPStatusError].any? {|ex| request_error.kind_of? ex }
|
201
|
-
retries_remaining ||=
|
204
|
+
retries_remaining ||= retry_limit
|
202
205
|
retries_remaining -= 1
|
203
206
|
if retries_remaining > 0
|
204
207
|
if params[:body].respond_to?(:pos=)
|
@@ -226,6 +229,12 @@ module Excon
|
|
226
229
|
DEF
|
227
230
|
end
|
228
231
|
|
232
|
+
attr_writer :retry_limit
|
233
|
+
|
234
|
+
def retry_limit
|
235
|
+
@retry_limit ||= DEFAULT_RETRY_LIMIT
|
236
|
+
end
|
237
|
+
|
229
238
|
private
|
230
239
|
|
231
240
|
def socket
|
data/lib/excon/constants.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Excon
|
2
2
|
unless const_defined?(:VERSION)
|
3
|
-
VERSION = '0.7.
|
3
|
+
VERSION = '0.7.9'
|
4
4
|
end
|
5
5
|
|
6
6
|
unless const_defined?(:CHUNK_SIZE)
|
@@ -11,6 +11,10 @@ module Excon
|
|
11
11
|
HTTP_VERBS = %w{connect delete get head options post put trace}
|
12
12
|
end
|
13
13
|
|
14
|
+
unless const_defined?(:DEFAULT_RETRY_LIMIT)
|
15
|
+
DEFAULT_RETRY_LIMIT = 4
|
16
|
+
end
|
17
|
+
|
14
18
|
unless ::IO.const_defined?(:WaitReadable)
|
15
19
|
class ::IO
|
16
20
|
module WaitReadable; end
|
@@ -22,5 +26,4 @@ module Excon
|
|
22
26
|
module WaitWritable; end
|
23
27
|
end
|
24
28
|
end
|
25
|
-
|
26
29
|
end
|
data/lib/excon/socket.rb
CHANGED
@@ -13,34 +13,54 @@ module Excon
|
|
13
13
|
@read_buffer, @write_buffer = '', ''
|
14
14
|
@eof = false
|
15
15
|
|
16
|
+
connect
|
17
|
+
end
|
18
|
+
|
19
|
+
def connect
|
20
|
+
@socket = nil
|
21
|
+
exception = nil
|
22
|
+
|
16
23
|
addrinfo = if @proxy
|
17
24
|
::Socket.getaddrinfo(@proxy[:host], @proxy[:port].to_i, nil, ::Socket::Constants::SOCK_STREAM)
|
18
25
|
else
|
19
26
|
::Socket.getaddrinfo(@params[:host], @params[:port].to_i, nil, ::Socket::Constants::SOCK_STREAM)
|
20
|
-
end
|
21
|
-
|
22
|
-
_, port, _, ip, a_family, s_type = addrinfo
|
27
|
+
end
|
23
28
|
|
24
|
-
|
29
|
+
addrinfo.each do |_, port, _, ip, a_family, s_type|
|
30
|
+
# nonblocking connect
|
31
|
+
begin
|
32
|
+
sockaddr = ::Socket.sockaddr_in(port, ip)
|
25
33
|
|
26
|
-
|
34
|
+
socket = ::Socket.new(a_family, s_type, 0)
|
27
35
|
|
28
|
-
|
36
|
+
socket.connect_nonblock(sockaddr)
|
29
37
|
|
30
|
-
|
31
|
-
|
38
|
+
@socket = socket
|
39
|
+
break
|
40
|
+
rescue Errno::EINPROGRESS
|
41
|
+
IO.select(nil, [socket], nil, @params[:connect_timeout])
|
42
|
+
begin
|
43
|
+
socket.connect_nonblock(sockaddr)
|
32
44
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
45
|
+
@socket = socket
|
46
|
+
break
|
47
|
+
rescue Errno::EISCONN
|
48
|
+
@socket = socket
|
49
|
+
break
|
50
|
+
rescue SystemCallError => exception
|
51
|
+
socket.close
|
52
|
+
next
|
53
|
+
end
|
54
|
+
rescue SystemCallError => exception
|
55
|
+
socket.close
|
56
|
+
next
|
42
57
|
end
|
43
58
|
end
|
59
|
+
|
60
|
+
unless @socket
|
61
|
+
# this will be our last encountered exception
|
62
|
+
raise exception
|
63
|
+
end
|
44
64
|
end
|
45
65
|
|
46
66
|
def read(max_length=nil)
|
data/lib/excon/ssl_socket.rb
CHANGED
data/tests/idempotent_tests.rb
CHANGED
@@ -10,7 +10,7 @@ Shindo.tests('Excon request idempotencey') do
|
|
10
10
|
run_count = 0
|
11
11
|
Excon.stub({:method => :get}) { |params|
|
12
12
|
run_count += 1
|
13
|
-
if run_count
|
13
|
+
if run_count <= 3 # First 3 calls fail.
|
14
14
|
raise Excon::Errors::SocketError.new(Exception.new "Mock Error")
|
15
15
|
else
|
16
16
|
{:body => params[:body], :headers => params[:headers], :status => 200}
|
@@ -53,5 +53,93 @@ Shindo.tests('Excon request idempotencey') do
|
|
53
53
|
response.status
|
54
54
|
end
|
55
55
|
|
56
|
+
tests("Lowered retry limit with socket erroring first time").returns(200) do
|
57
|
+
run_count = 0
|
58
|
+
Excon.stub({:method => :get}) { |params|
|
59
|
+
run_count += 1
|
60
|
+
if run_count <= 1 # First call fails.
|
61
|
+
raise Excon::Errors::SocketError.new(Exception.new "Mock Error")
|
62
|
+
else
|
63
|
+
{:body => params[:body], :headers => params[:headers], :status => 200}
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
connection = Excon.new('http://127.0.0.1:9292')
|
68
|
+
connection.retry_limit = 2
|
69
|
+
response = connection.request(:method => :get, :idempotent => true, :path => '/some-path')
|
70
|
+
response.status
|
71
|
+
end
|
72
|
+
|
73
|
+
tests("Lowered retry limit with socket erroring first 3 times").raises(Excon::Errors::SocketError) do
|
74
|
+
run_count = 0
|
75
|
+
Excon.stub({:method => :get}) { |params|
|
76
|
+
run_count += 1
|
77
|
+
if run_count <= 3 # First 3 calls fail.
|
78
|
+
raise Excon::Errors::SocketError.new(Exception.new "Mock Error")
|
79
|
+
else
|
80
|
+
{:body => params[:body], :headers => params[:headers], :status => 200}
|
81
|
+
end
|
82
|
+
}
|
83
|
+
|
84
|
+
connection = Excon.new('http://127.0.0.1:9292')
|
85
|
+
connection.retry_limit = 2
|
86
|
+
response = connection.request(:method => :get, :idempotent => true, :path => '/some-path')
|
87
|
+
response.status
|
88
|
+
end
|
89
|
+
|
90
|
+
tests("Raised retry limit with socket erroring first 5 times").returns(200) do
|
91
|
+
run_count = 0
|
92
|
+
Excon.stub({:method => :get}) { |params|
|
93
|
+
run_count += 1
|
94
|
+
if run_count <= 5 # First 5 calls fail.
|
95
|
+
raise Excon::Errors::SocketError.new(Exception.new "Mock Error")
|
96
|
+
else
|
97
|
+
{:body => params[:body], :headers => params[:headers], :status => 200}
|
98
|
+
end
|
99
|
+
}
|
100
|
+
|
101
|
+
connection = Excon.new('http://127.0.0.1:9292')
|
102
|
+
connection.retry_limit = 8
|
103
|
+
response = connection.request(:method => :get, :idempotent => true, :path => '/some-path')
|
104
|
+
response.status
|
105
|
+
end
|
106
|
+
|
107
|
+
tests("Raised retry limit with socket erroring first 9 times").raises(Excon::Errors::SocketError) do
|
108
|
+
run_count = 0
|
109
|
+
Excon.stub({:method => :get}) { |params|
|
110
|
+
run_count += 1
|
111
|
+
if run_count <= 9 # First 9 calls fail.
|
112
|
+
raise Excon::Errors::SocketError.new(Exception.new "Mock Error")
|
113
|
+
else
|
114
|
+
{:body => params[:body], :headers => params[:headers], :status => 200}
|
115
|
+
end
|
116
|
+
}
|
117
|
+
|
118
|
+
connection = Excon.new('http://127.0.0.1:9292')
|
119
|
+
connection.retry_limit = 8
|
120
|
+
response = connection.request(:method => :get, :idempotent => true, :path => '/some-path')
|
121
|
+
response.status
|
122
|
+
end
|
123
|
+
|
124
|
+
tests("Retry limit in constructor with socket erroring first 5 times").returns(200) do
|
125
|
+
run_count = 0
|
126
|
+
|
127
|
+
connection = Excon.new('http://127.0.0.1:9292', :retry_limit => 6)
|
128
|
+
tests("setter sets").returns(6) do
|
129
|
+
connection.retry_limit
|
130
|
+
end
|
131
|
+
|
132
|
+
Excon.stub({:method => :get}) { |params|
|
133
|
+
run_count += 1
|
134
|
+
if run_count <= 5 # First 5 calls fail.
|
135
|
+
raise Excon::Errors::SocketError.new(Exception.new "Mock Error")
|
136
|
+
else
|
137
|
+
{:body => params[:body], :headers => params[:headers], :status => 200}
|
138
|
+
end
|
139
|
+
}
|
140
|
+
response = connection.request(:method => :get, :idempotent => true, :path => '/some-path')
|
141
|
+
response.status
|
142
|
+
end
|
143
|
+
|
56
144
|
Excon.mock = false
|
57
145
|
end
|
@@ -5,18 +5,18 @@ Shindo.tests('Excon request methods') do
|
|
5
5
|
tests 'one-offs' do
|
6
6
|
|
7
7
|
tests('Excon.get').returns('GET') do
|
8
|
-
Excon.get('http://
|
8
|
+
Excon.get('http://localhost:9292').body
|
9
9
|
end
|
10
10
|
|
11
11
|
tests('Excon.post').returns('POST') do
|
12
|
-
Excon.post('http://
|
12
|
+
Excon.post('http://localhost:9292').body
|
13
13
|
end
|
14
14
|
|
15
15
|
end
|
16
16
|
|
17
17
|
tests 'with a connection object' do
|
18
18
|
|
19
|
-
connection = Excon.new('http://
|
19
|
+
connection = Excon.new('http://localhost:9292')
|
20
20
|
|
21
21
|
tests('connection.get').returns('GET') do
|
22
22
|
connection.get.body
|
data/tests/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,72 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 17
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 7
|
8
|
-
-
|
9
|
-
version: 0.7.
|
9
|
+
- 9
|
10
|
+
version: 0.7.9
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
13
|
+
- dpiddy (Dan Peterson)
|
12
14
|
- geemus (Wesley Beary)
|
15
|
+
- nextmat (Matt Sanders)
|
13
16
|
autorequire:
|
14
17
|
bindir: bin
|
15
18
|
cert_chain: []
|
16
19
|
|
17
|
-
date: 2011-11-
|
20
|
+
date: 2011-11-30 00:00:00 -04:00
|
18
21
|
default_executable:
|
19
22
|
dependencies:
|
20
23
|
- !ruby/object:Gem::Dependency
|
21
|
-
name: open4
|
22
|
-
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
27
30
|
segments:
|
28
31
|
- 0
|
29
32
|
version: "0"
|
30
|
-
type: :development
|
31
33
|
version_requirements: *id001
|
32
|
-
|
33
|
-
name: rake
|
34
|
+
name: open4
|
34
35
|
prerelease: false
|
36
|
+
type: :development
|
37
|
+
- !ruby/object:Gem::Dependency
|
35
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
36
40
|
requirements:
|
37
41
|
- - ">="
|
38
42
|
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
39
44
|
segments:
|
40
45
|
- 0
|
41
46
|
version: "0"
|
42
|
-
type: :development
|
43
47
|
version_requirements: *id002
|
44
|
-
|
45
|
-
name: shindo
|
48
|
+
name: rake
|
46
49
|
prerelease: false
|
50
|
+
type: :development
|
51
|
+
- !ruby/object:Gem::Dependency
|
47
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
48
54
|
requirements:
|
49
55
|
- - "="
|
50
56
|
- !ruby/object:Gem::Version
|
57
|
+
hash: 23
|
51
58
|
segments:
|
52
59
|
- 0
|
53
60
|
- 2
|
54
61
|
- 0
|
55
62
|
version: 0.2.0
|
56
|
-
type: :development
|
57
63
|
version_requirements: *id003
|
58
|
-
|
59
|
-
name: sinatra
|
64
|
+
name: shindo
|
60
65
|
prerelease: false
|
66
|
+
type: :development
|
67
|
+
- !ruby/object:Gem::Dependency
|
61
68
|
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
62
70
|
requirements:
|
63
71
|
- - ">="
|
64
72
|
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
65
74
|
segments:
|
66
75
|
- 0
|
67
76
|
version: "0"
|
68
|
-
type: :development
|
69
77
|
version_requirements: *id004
|
78
|
+
name: sinatra
|
79
|
+
prerelease: false
|
80
|
+
type: :development
|
70
81
|
description: EXtended http(s) CONnections
|
71
82
|
email: geemus@gmail.com
|
72
83
|
executables: []
|
@@ -133,23 +144,27 @@ rdoc_options:
|
|
133
144
|
require_paths:
|
134
145
|
- lib
|
135
146
|
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
136
148
|
requirements:
|
137
149
|
- - ">="
|
138
150
|
- !ruby/object:Gem::Version
|
151
|
+
hash: 3
|
139
152
|
segments:
|
140
153
|
- 0
|
141
154
|
version: "0"
|
142
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
+
none: false
|
143
157
|
requirements:
|
144
158
|
- - ">="
|
145
159
|
- !ruby/object:Gem::Version
|
160
|
+
hash: 3
|
146
161
|
segments:
|
147
162
|
- 0
|
148
163
|
version: "0"
|
149
164
|
requirements: []
|
150
165
|
|
151
166
|
rubyforge_project: excon
|
152
|
-
rubygems_version: 1.
|
167
|
+
rubygems_version: 1.6.2
|
153
168
|
signing_key:
|
154
169
|
specification_version: 2
|
155
170
|
summary: speed, persistence, http(s)
|