excon 0.28.0 → 0.29.0
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/Gemfile.lock +1 -1
- data/README.md +4 -3
- data/changelog.txt +13 -0
- data/excon.gemspec +2 -2
- data/lib/excon.rb +7 -7
- data/lib/excon/connection.rb +26 -14
- data/lib/excon/constants.rb +2 -2
- data/lib/excon/middlewares/redirect_follower.rb +1 -0
- data/lib/excon/response.rb +11 -7
- data/lib/excon/socket.rb +37 -8
- data/lib/excon/ssl_socket.rb +3 -16
- metadata +3 -3
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -8,6 +8,7 @@ Excon was designed to be simple, fast and performant. It works great as a genera
|
|
8
8
|
[![Build Status](https://secure.travis-ci.org/geemus/excon.png)](http://travis-ci.org/geemus/excon)
|
9
9
|
[![Dependency Status](https://gemnasium.com/geemus/excon.png)](https://gemnasium.com/geemus/excon)
|
10
10
|
[![Gem Version](https://fury-badge.herokuapp.com/rb/excon.png)](http://badge.fury.io/rb/excon)
|
11
|
+
[![Gittip](http://img.shields.io/gittip/geemus.png)](https://www.gittip.com/geemus/)
|
11
12
|
|
12
13
|
Getting Started
|
13
14
|
---------------
|
@@ -83,9 +84,6 @@ connection.request(:idempotent => true)
|
|
83
84
|
# this request can be repeated safely, retry up to 6 times
|
84
85
|
connection.request(:idempotent => true, :retry_limit => 6)
|
85
86
|
|
86
|
-
# opt-out of nonblocking operations for performance and/or as a workaround
|
87
|
-
connection.request(:nonblock => false)
|
88
|
-
|
89
87
|
# set longer read_timeout (default is 60 seconds)
|
90
88
|
connection.request(:read_timeout => 360)
|
91
89
|
|
@@ -104,6 +102,9 @@ connection = Excon.new('http://geemus.com/', :omit_default_port => true)
|
|
104
102
|
|
105
103
|
# set longer connect_timeout (default is 60 seconds)
|
106
104
|
connection = Excon.new('http://geemus.com/', :connect_timeout => 360)
|
105
|
+
|
106
|
+
# opt-out of nonblocking operations for performance and/or as a workaround
|
107
|
+
connection = Excon.new('http://geemus.com/', :nonblock => false)
|
107
108
|
```
|
108
109
|
|
109
110
|
Chunked Requests
|
data/changelog.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
0.29.0 11/07/2013
|
2
|
+
=================
|
3
|
+
|
4
|
+
make nonblock invalid as request key
|
5
|
+
add backtrace to all warnings
|
6
|
+
do not allow idempotent + pipeline
|
7
|
+
close socket after pipeline if needed
|
8
|
+
fix Socket#read to match IO.read EOF behavior
|
9
|
+
use Socket#read for non-blocking readline
|
10
|
+
respect read_timeout for status read
|
11
|
+
read response until status line, discard chunked trailer
|
12
|
+
fix redirect follower to properly change host
|
13
|
+
|
1
14
|
0.28.0 10/28/2013
|
2
15
|
=================
|
3
16
|
|
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.
|
17
|
-
s.date = '2013-
|
16
|
+
s.version = '0.29.0'
|
17
|
+
s.date = '2013-11-07'
|
18
18
|
s.rubyforge_project = 'excon'
|
19
19
|
|
20
20
|
## Make sure your summary is short. The description may be as long
|
data/lib/excon.rb
CHANGED
@@ -80,13 +80,13 @@ module Excon
|
|
80
80
|
def display_warning(warning)
|
81
81
|
# Respect Ruby's $VERBOSE setting, unless EXCON_DEBUG is set
|
82
82
|
if !$VERBOSE.nil? || ENV['EXCON_DEBUG']
|
83
|
-
$stderr.puts
|
83
|
+
$stderr.puts '[excon][WARNING] ' << warning << "\n#{ caller.join("\n") }"
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
# Status of mocking
|
88
88
|
def mock
|
89
|
-
display_warning(
|
89
|
+
display_warning('Excon#mock is deprecated, use Excon.defaults[:mock] instead.')
|
90
90
|
self.defaults[:mock]
|
91
91
|
end
|
92
92
|
|
@@ -94,33 +94,33 @@ module Excon
|
|
94
94
|
# false is the default and works as expected
|
95
95
|
# true returns a value from stubs or raises
|
96
96
|
def mock=(new_mock)
|
97
|
-
display_warning(
|
97
|
+
display_warning('Excon#mock is deprecated, use Excon.defaults[:mock]= instead.')
|
98
98
|
self.defaults[:mock] = new_mock
|
99
99
|
end
|
100
100
|
|
101
101
|
# @return [String] The filesystem path to the SSL Certificate Authority
|
102
102
|
def ssl_ca_path
|
103
|
-
display_warning(
|
103
|
+
display_warning('Excon#ssl_ca_path is deprecated, use Excon.defaults[:ssl_ca_path] instead.')
|
104
104
|
self.defaults[:ssl_ca_path]
|
105
105
|
end
|
106
106
|
|
107
107
|
# Change path to the SSL Certificate Authority
|
108
108
|
# @return [String] The filesystem path to the SSL Certificate Authority
|
109
109
|
def ssl_ca_path=(new_ssl_ca_path)
|
110
|
-
display_warning(
|
110
|
+
display_warning('Excon#ssl_ca_path= is deprecated, use Excon.defaults[:ssl_ca_path]= instead.')
|
111
111
|
self.defaults[:ssl_ca_path] = new_ssl_ca_path
|
112
112
|
end
|
113
113
|
|
114
114
|
# @return [true, false] Whether or not to verify the peer's SSL certificate / chain
|
115
115
|
def ssl_verify_peer
|
116
|
-
display_warning(
|
116
|
+
display_warning('Excon#ssl_verify_peer is deprecated, use Excon.defaults[:ssl_verify_peer] instead.')
|
117
117
|
self.defaults[:ssl_verify_peer]
|
118
118
|
end
|
119
119
|
|
120
120
|
# Change the status of ssl peer verification
|
121
121
|
# @see Excon#ssl_verify_peer (attr_reader)
|
122
122
|
def ssl_verify_peer=(new_ssl_verify_peer)
|
123
|
-
display_warning(
|
123
|
+
display_warning('Excon#ssl_verify_peer= is deprecated, use Excon.defaults[:ssl_verify_peer]= instead.')
|
124
124
|
self.defaults[:ssl_verify_peer] = new_ssl_verify_peer
|
125
125
|
end
|
126
126
|
|
data/lib/excon/connection.rb
CHANGED
@@ -5,29 +5,29 @@ module Excon
|
|
5
5
|
attr_reader :data
|
6
6
|
|
7
7
|
def connection
|
8
|
-
Excon.display_warning(
|
8
|
+
Excon.display_warning('Excon::Connection#connection is deprecated use Excon::Connection#data instead.')
|
9
9
|
@data
|
10
10
|
end
|
11
11
|
def connection=(new_params)
|
12
|
-
Excon.display_warning(
|
12
|
+
Excon.display_warning('Excon::Connection#connection= is deprecated. Use of this method may cause unexpected results.')
|
13
13
|
@data = new_params
|
14
14
|
end
|
15
15
|
|
16
16
|
def params
|
17
|
-
Excon.display_warning(
|
17
|
+
Excon.display_warning('Excon::Connection#params is deprecated use Excon::Connection#data instead.')
|
18
18
|
@data
|
19
19
|
end
|
20
20
|
def params=(new_params)
|
21
|
-
Excon.display_warning(
|
21
|
+
Excon.display_warning('Excon::Connection#params= is deprecated. Use of this method may cause unexpected results.')
|
22
22
|
@data = new_params
|
23
23
|
end
|
24
24
|
|
25
25
|
def proxy
|
26
|
-
Excon.display_warning(
|
26
|
+
Excon.display_warning('Excon::Connection#proxy is deprecated use Excon::Connection#data[:proxy] instead.')
|
27
27
|
@data[:proxy]
|
28
28
|
end
|
29
29
|
def proxy=(new_proxy)
|
30
|
-
Excon.display_warning(
|
30
|
+
Excon.display_warning('Excon::Connection#proxy= is deprecated. Use of this method may cause unexpected results.')
|
31
31
|
@data[:proxy] = new_proxy
|
32
32
|
end
|
33
33
|
|
@@ -232,13 +232,19 @@ module Excon
|
|
232
232
|
end
|
233
233
|
|
234
234
|
if block_given?
|
235
|
-
Excon.display_warning(
|
235
|
+
Excon.display_warning('Excon requests with a block are deprecated, pass :response_block instead.')
|
236
236
|
datum[:response_block] = Proc.new
|
237
237
|
end
|
238
238
|
|
239
|
-
if datum[:
|
240
|
-
|
241
|
-
|
239
|
+
if datum[:idempotent]
|
240
|
+
if datum[:request_block]
|
241
|
+
Excon.display_warning('Excon requests with a :request_block can not be :idempotent.')
|
242
|
+
datum[:idempotent] = false
|
243
|
+
end
|
244
|
+
if datum[:pipeline]
|
245
|
+
Excon.display_warning("Excon requests can not be :idempotent when pipelining.")
|
246
|
+
datum[:idempotent] = false
|
247
|
+
end
|
242
248
|
end
|
243
249
|
|
244
250
|
datum[:connection] = self
|
@@ -274,11 +280,17 @@ module Excon
|
|
274
280
|
# Sends the supplied requests to the destination host using pipelining.
|
275
281
|
# @pipeline_params [Array<Hash>] pipeline_params An array of one or more optional params, override defaults set in Connection.new, see #request for details
|
276
282
|
def requests(pipeline_params)
|
277
|
-
pipeline_params.map do |params|
|
283
|
+
responses = pipeline_params.map do |params|
|
278
284
|
request(params.merge!(:pipeline => true))
|
279
285
|
end.map do |datum|
|
280
286
|
Excon::Response.new(response(datum)[:response])
|
281
287
|
end
|
288
|
+
|
289
|
+
if responses.last[:headers]['Connection'] == 'close'
|
290
|
+
reset
|
291
|
+
end
|
292
|
+
|
293
|
+
responses
|
282
294
|
end
|
283
295
|
|
284
296
|
def reset
|
@@ -295,12 +307,12 @@ module Excon
|
|
295
307
|
end
|
296
308
|
|
297
309
|
def retry_limit=(new_retry_limit)
|
298
|
-
Excon.display_warning(
|
310
|
+
Excon.display_warning('Excon::Connection#retry_limit= is deprecated, pass :retry_limit to the initializer.')
|
299
311
|
@data[:retry_limit] = new_retry_limit
|
300
312
|
end
|
301
313
|
|
302
314
|
def retry_limit
|
303
|
-
Excon.display_warning(
|
315
|
+
Excon.display_warning('Excon::Connection#retry_limit is deprecated, use Excon::Connection#data[:retry_limit].')
|
304
316
|
@data[:retry_limit] ||= DEFAULT_RETRY_LIMIT
|
305
317
|
end
|
306
318
|
|
@@ -349,7 +361,7 @@ module Excon
|
|
349
361
|
end
|
350
362
|
invalid_keys = params.keys - valid_keys
|
351
363
|
unless invalid_keys.empty?
|
352
|
-
Excon.display_warning("Invalid Excon #{validation} keys: #{invalid_keys.map(&:inspect).join(', ')}
|
364
|
+
Excon.display_warning("Invalid Excon #{validation} keys: #{invalid_keys.map(&:inspect).join(', ')}")
|
353
365
|
# FIXME: for now, just warn, don't mutate, give things (ie fog) a chance to catch up
|
354
366
|
#params = params.dup
|
355
367
|
#invalid_keys.each {|key| params.delete(key) }
|
data/lib/excon/constants.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Excon
|
2
2
|
|
3
|
-
VERSION = '0.
|
3
|
+
VERSION = '0.29.0'
|
4
4
|
|
5
5
|
CR_NL = "\r\n"
|
6
6
|
|
@@ -49,7 +49,6 @@ module Excon
|
|
49
49
|
:method,
|
50
50
|
:middlewares,
|
51
51
|
:mock,
|
52
|
-
:nonblock,
|
53
52
|
:path,
|
54
53
|
:pipeline,
|
55
54
|
:query,
|
@@ -73,6 +72,7 @@ module Excon
|
|
73
72
|
:family,
|
74
73
|
:host,
|
75
74
|
:omit_default_port,
|
75
|
+
:nonblock,
|
76
76
|
:password,
|
77
77
|
:port,
|
78
78
|
:proxy,
|
data/lib/excon/response.rb
CHANGED
@@ -30,13 +30,16 @@ module Excon
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.parse(socket, datum)
|
33
|
+
# this will discard any trailing lines from the previous response if any.
|
34
|
+
until match = /^HTTP\/\d+\.\d+\s(\d{3})\s/.match(socket.readline); end
|
35
|
+
status = match[1].to_i
|
36
|
+
|
33
37
|
datum[:response] = {
|
34
38
|
:body => '',
|
35
39
|
:headers => {},
|
36
|
-
:status =>
|
40
|
+
:status => status,
|
37
41
|
:remote_ip => socket.respond_to?(:remote_ip) && socket.remote_ip
|
38
42
|
}
|
39
|
-
socket.readline # read the rest of the status line and CRLF
|
40
43
|
|
41
44
|
until ((data = socket.readline).chop!).empty?
|
42
45
|
key, value = data.split(/:\s*/, 2)
|
@@ -56,11 +59,11 @@ module Excon
|
|
56
59
|
# if expects matched and there is a block, use it
|
57
60
|
if expected_status && datum.has_key?(:response_block)
|
58
61
|
if transfer_encoding_chunked
|
59
|
-
# 2 == "
|
62
|
+
# 2 == "\r\n".length
|
60
63
|
while (chunk_size = socket.readline.chop!.to_i(16)) > 0
|
61
64
|
datum[:response_block].call(socket.read(chunk_size + 2).chop!, nil, nil)
|
62
65
|
end
|
63
|
-
socket.read(2)
|
66
|
+
socket.read(2) # empty chunk-body
|
64
67
|
elsif remaining = content_length
|
65
68
|
while remaining > 0
|
66
69
|
datum[:response_block].call(socket.read([datum[:chunk_size], remaining].min), [remaining - datum[:chunk_size], 0].max, content_length)
|
@@ -73,10 +76,11 @@ module Excon
|
|
73
76
|
end
|
74
77
|
else # no block or unexpected status
|
75
78
|
if transfer_encoding_chunked
|
79
|
+
# 2 == "\r\n".length
|
76
80
|
while (chunk_size = socket.readline.chop!.to_i(16)) > 0
|
77
|
-
datum[:response][:body] << socket.read(chunk_size + 2).chop!
|
81
|
+
datum[:response][:body] << socket.read(chunk_size + 2).chop!
|
78
82
|
end
|
79
|
-
socket.read(2) #
|
83
|
+
socket.read(2) # empty chunk-body
|
80
84
|
elsif remaining = content_length
|
81
85
|
while remaining > 0
|
82
86
|
datum[:response][:body] << socket.read([datum[:chunk_size], remaining].min)
|
@@ -106,7 +110,7 @@ module Excon
|
|
106
110
|
end
|
107
111
|
|
108
112
|
def params
|
109
|
-
Excon.display_warning(
|
113
|
+
Excon.display_warning('Excon::Response#params is deprecated use Excon::Response#data instead.')
|
110
114
|
data
|
111
115
|
end
|
112
116
|
|
data/lib/excon/socket.rb
CHANGED
@@ -7,21 +7,21 @@ module Excon
|
|
7
7
|
attr_accessor :data
|
8
8
|
|
9
9
|
def params
|
10
|
-
Excon.display_warning(
|
10
|
+
Excon.display_warning('Excon::Socket#params is deprecated use Excon::Socket#data instead.')
|
11
11
|
@data
|
12
12
|
end
|
13
13
|
def params=(new_params)
|
14
|
-
Excon.display_warning(
|
14
|
+
Excon.display_warning('Excon::Socket#params= is deprecated use Excon::Socket#data= instead.')
|
15
15
|
@data = new_params
|
16
16
|
end
|
17
17
|
|
18
18
|
attr_reader :remote_ip
|
19
19
|
|
20
20
|
def_delegators(:@socket, :close, :close)
|
21
|
-
def_delegators(:@socket, :readline, :readline)
|
22
21
|
|
23
22
|
def initialize(data = {})
|
24
23
|
@data = data
|
24
|
+
@nonblock = data[:nonblock]
|
25
25
|
@read_buffer = ''
|
26
26
|
@eof = false
|
27
27
|
|
@@ -30,8 +30,8 @@ module Excon
|
|
30
30
|
|
31
31
|
def read(max_length=nil)
|
32
32
|
if @eof
|
33
|
-
return nil
|
34
|
-
elsif @
|
33
|
+
return max_length ? nil : ''
|
34
|
+
elsif @nonblock
|
35
35
|
begin
|
36
36
|
if max_length
|
37
37
|
until @read_buffer.length >= max_length
|
@@ -61,8 +61,13 @@ module Excon
|
|
61
61
|
rescue EOFError
|
62
62
|
@eof = true
|
63
63
|
end
|
64
|
+
|
64
65
|
if max_length
|
65
|
-
@read_buffer.
|
66
|
+
if @read_buffer.empty?
|
67
|
+
nil # EOF met at beginning
|
68
|
+
else
|
69
|
+
@read_buffer.slice!(0, max_length)
|
70
|
+
end
|
66
71
|
else
|
67
72
|
# read until EOFError, so return everything
|
68
73
|
@read_buffer.slice!(0, @read_buffer.length)
|
@@ -78,8 +83,32 @@ module Excon
|
|
78
83
|
end
|
79
84
|
end
|
80
85
|
|
86
|
+
def readline
|
87
|
+
if @eof
|
88
|
+
raise EOFError, 'end of file reached'
|
89
|
+
else
|
90
|
+
line = ''
|
91
|
+
if @nonblock
|
92
|
+
while char = read(1)
|
93
|
+
line << char
|
94
|
+
break if char == $/
|
95
|
+
end
|
96
|
+
raise EOFError, 'end of file reached' if line.empty?
|
97
|
+
else
|
98
|
+
begin
|
99
|
+
Timeout.timeout(@data[:read_timeout]) do
|
100
|
+
line = @socket.readline
|
101
|
+
end
|
102
|
+
rescue Timeout::Error
|
103
|
+
raise Excon::Errors::Timeout.new('read timeout reached')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
line
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
81
110
|
def write(data)
|
82
|
-
if @
|
111
|
+
if @nonblock
|
83
112
|
if FORCE_ENC
|
84
113
|
data.force_encoding('BINARY')
|
85
114
|
end
|
@@ -144,7 +173,7 @@ module Excon
|
|
144
173
|
|
145
174
|
socket = ::Socket.new(a_family, s_type, 0)
|
146
175
|
|
147
|
-
if @
|
176
|
+
if @nonblock
|
148
177
|
socket.connect_nonblock(sockaddr)
|
149
178
|
else
|
150
179
|
begin
|
data/lib/excon/ssl_socket.rb
CHANGED
@@ -2,9 +2,6 @@ module Excon
|
|
2
2
|
class SSLSocket < Socket
|
3
3
|
|
4
4
|
def initialize(data = {})
|
5
|
-
@data = data
|
6
|
-
check_nonblock_support
|
7
|
-
|
8
5
|
super
|
9
6
|
|
10
7
|
# create ssl context
|
@@ -30,7 +27,7 @@ module Excon
|
|
30
27
|
begin
|
31
28
|
ssl_context.cert_store.add_file(ca_file)
|
32
29
|
rescue => e
|
33
|
-
Excon.display_warning("Excon unable to add file to cert store, ignoring: #{ca_file}\n[#{e.class}] #{e.message}
|
30
|
+
Excon.display_warning("Excon unable to add file to cert store, ignoring: #{ca_file}\n[#{e.class}] #{e.message}")
|
34
31
|
end
|
35
32
|
end
|
36
33
|
else
|
@@ -88,22 +85,12 @@ module Excon
|
|
88
85
|
@socket
|
89
86
|
end
|
90
87
|
|
91
|
-
def read(max_length=nil)
|
92
|
-
check_nonblock_support
|
93
|
-
super
|
94
|
-
end
|
95
|
-
|
96
|
-
def write(data)
|
97
|
-
check_nonblock_support
|
98
|
-
super
|
99
|
-
end
|
100
|
-
|
101
88
|
private
|
102
89
|
|
103
90
|
def check_nonblock_support
|
104
91
|
# backwards compatability for things lacking nonblock
|
105
|
-
if !DEFAULT_NONBLOCK && @
|
106
|
-
@
|
92
|
+
if !DEFAULT_NONBLOCK && @nonblock
|
93
|
+
@nonblock = false
|
107
94
|
end
|
108
95
|
end
|
109
96
|
|
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.
|
4
|
+
version: 0.29.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-
|
14
|
+
date: 2013-11-07 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activesupport
|
@@ -245,7 +245,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
245
245
|
version: '0'
|
246
246
|
segments:
|
247
247
|
- 0
|
248
|
-
hash:
|
248
|
+
hash: -2194157728593914934
|
249
249
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
250
250
|
none: false
|
251
251
|
requirements:
|