excon 0.31.0 → 0.32.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.
- checksums.yaml +15 -0
- data/CONTRIBUTING.md +23 -0
- data/CONTRIBUTORS.md +90 -0
- data/Gemfile.lock +1 -1
- data/LICENSE.md +20 -0
- data/README.md +35 -67
- data/Rakefile +9 -0
- data/changelog.txt +16 -0
- data/data/cacert.pem +352 -463
- data/excon.gemspec +7 -2
- data/lib/excon.rb +1 -2
- data/lib/excon/connection.rb +2 -2
- data/lib/excon/constants.rb +2 -1
- data/lib/excon/middlewares/escape_path.rb +11 -0
- data/lib/excon/response.rb +18 -8
- data/lib/excon/socket.rb +34 -11
- data/lib/excon/ssl_socket.rb +35 -2
- data/lib/excon/utils.rb +14 -1
- data/tests/basic_tests.rb +69 -0
- data/tests/middlewares/escape_path_tests.rb +34 -0
- data/tests/rackups/basic.rb +4 -0
- data/tests/servers/good.rb +1 -0
- metadata +9 -25
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 = '
|
16
|
+
s.version = '0.32.0'
|
17
|
+
s.date = '2014-02-27'
|
18
18
|
s.rubyforge_project = 'excon'
|
19
19
|
|
20
20
|
## Make sure your summary is short. The description may be as long
|
@@ -68,8 +68,11 @@ Gem::Specification.new do |s|
|
|
68
68
|
## THE MANIFEST COMMENTS, they are used as delimiters by the task.
|
69
69
|
# = MANIFEST =
|
70
70
|
s.files = %w[
|
71
|
+
CONTRIBUTING.md
|
72
|
+
CONTRIBUTORS.md
|
71
73
|
Gemfile
|
72
74
|
Gemfile.lock
|
75
|
+
LICENSE.md
|
73
76
|
README.md
|
74
77
|
Rakefile
|
75
78
|
benchmarks/class_vs_lambda.rb
|
@@ -99,6 +102,7 @@ Gem::Specification.new do |s|
|
|
99
102
|
lib/excon/errors.rb
|
100
103
|
lib/excon/middlewares/base.rb
|
101
104
|
lib/excon/middlewares/decompress.rb
|
105
|
+
lib/excon/middlewares/escape_path.rb
|
102
106
|
lib/excon/middlewares/expects.rb
|
103
107
|
lib/excon/middlewares/idempotent.rb
|
104
108
|
lib/excon/middlewares/instrumentor.rb
|
@@ -121,6 +125,7 @@ Gem::Specification.new do |s|
|
|
121
125
|
tests/header_tests.rb
|
122
126
|
tests/middlewares/canned_response_tests.rb
|
123
127
|
tests/middlewares/decompress_tests.rb
|
128
|
+
tests/middlewares/escape_path_tests.rb
|
124
129
|
tests/middlewares/idempotent_tests.rb
|
125
130
|
tests/middlewares/instrumentation_tests.rb
|
126
131
|
tests/middlewares/mock_tests.rb
|
data/lib/excon.rb
CHANGED
@@ -11,8 +11,6 @@ require 'uri'
|
|
11
11
|
require 'zlib'
|
12
12
|
require 'stringio'
|
13
13
|
|
14
|
-
BasicSocket.do_not_reverse_lookup = true
|
15
|
-
|
16
14
|
# Define defaults first so they will be available to other files
|
17
15
|
module Excon
|
18
16
|
class << self
|
@@ -65,6 +63,7 @@ require 'excon/connection'
|
|
65
63
|
require 'excon/errors'
|
66
64
|
require 'excon/middlewares/base'
|
67
65
|
require 'excon/middlewares/decompress'
|
66
|
+
require 'excon/middlewares/escape_path'
|
68
67
|
require 'excon/middlewares/expects'
|
69
68
|
require 'excon/middlewares/idempotent'
|
70
69
|
require 'excon/middlewares/instrumentor'
|
data/lib/excon/connection.rb
CHANGED
@@ -269,7 +269,7 @@ module Excon
|
|
269
269
|
|
270
270
|
if datum[:persistent]
|
271
271
|
if key = datum[:response][:headers].keys.detect {|k| k.casecmp('Connection') == 0 }
|
272
|
-
if split_header_value(datum[:response][:headers][key]).any? {|t| t.casecmp('close') }
|
272
|
+
if split_header_value(datum[:response][:headers][key]).any? {|t| t.casecmp('close') == 0 }
|
273
273
|
reset
|
274
274
|
end
|
275
275
|
end
|
@@ -305,7 +305,7 @@ module Excon
|
|
305
305
|
|
306
306
|
if @data[:persistent]
|
307
307
|
if key = responses.last[:headers].keys.detect {|k| k.casecmp('Connection') == 0 }
|
308
|
-
if split_header_value(responses.last[:headers][key]).any? {|t| t.casecmp('close') }
|
308
|
+
if split_header_value(responses.last[:headers][key]).any? {|t| t.casecmp('close') == 0 }
|
309
309
|
reset
|
310
310
|
end
|
311
311
|
end
|
data/lib/excon/constants.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
module Excon
|
2
|
+
module Middleware
|
3
|
+
class EscapePath < Excon::Middleware::Base
|
4
|
+
def request_call(datum)
|
5
|
+
# make sure path is encoded, prevent double encoding
|
6
|
+
datum[:path] = Excon::Utils.escape_uri(Excon::Utils.unescape_uri(datum[:path]))
|
7
|
+
@stack.request_call(datum)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/excon/response.rb
CHANGED
@@ -28,6 +28,12 @@ module Excon
|
|
28
28
|
def remote_ip
|
29
29
|
@data[:remote_ip]
|
30
30
|
end
|
31
|
+
def local_port
|
32
|
+
@data[:local_port]
|
33
|
+
end
|
34
|
+
def local_address
|
35
|
+
@data[:local_address]
|
36
|
+
end
|
31
37
|
|
32
38
|
def self.parse(socket, datum)
|
33
39
|
# this will discard any trailing lines from the previous response if any.
|
@@ -35,10 +41,12 @@ module Excon
|
|
35
41
|
status = match[1].to_i
|
36
42
|
|
37
43
|
datum[:response] = {
|
38
|
-
:body
|
39
|
-
:headers
|
40
|
-
:status
|
41
|
-
:remote_ip
|
44
|
+
:body => '',
|
45
|
+
:headers => {},
|
46
|
+
:status => status,
|
47
|
+
:remote_ip => socket.respond_to?(:remote_ip) && socket.remote_ip,
|
48
|
+
:local_port => socket.respond_to?(:local_port) && socket.local_port,
|
49
|
+
:local_address => socket.respond_to?(:local_address) && socket.local_address
|
42
50
|
}
|
43
51
|
|
44
52
|
parse_headers(socket, datum)
|
@@ -126,10 +134,12 @@ module Excon
|
|
126
134
|
:body => '',
|
127
135
|
:headers => {}
|
128
136
|
}.merge(params)
|
129
|
-
@body
|
130
|
-
@headers
|
131
|
-
@status
|
132
|
-
@remote_ip
|
137
|
+
@body = @data[:body]
|
138
|
+
@headers = @data[:headers]
|
139
|
+
@status = @data[:status]
|
140
|
+
@remote_ip = @data[:remote_ip]
|
141
|
+
@local_port = @data[:local_port]
|
142
|
+
@local_address = @data[:local_address]
|
133
143
|
end
|
134
144
|
|
135
145
|
def [](key)
|
data/lib/excon/socket.rb
CHANGED
@@ -145,24 +145,40 @@ module Excon
|
|
145
145
|
@socket.write(data)
|
146
146
|
end
|
147
147
|
rescue Timeout::Error
|
148
|
-
Excon::Errors::Timeout.new('write timeout reached')
|
148
|
+
raise(Excon::Errors::Timeout.new('write timeout reached'))
|
149
149
|
end
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
+
def local_port
|
154
|
+
::Socket.unpack_sockaddr_in(@socket.to_io.getsockname)[0]
|
155
|
+
rescue ArgumentError => e
|
156
|
+
raise unless e.message == 'not an AF_INET/AF_INET6 sockaddr'
|
157
|
+
end
|
158
|
+
|
159
|
+
def local_address
|
160
|
+
::Socket.unpack_sockaddr_in(@socket.to_io.getsockname)[1]
|
161
|
+
rescue ArgumentError => e
|
162
|
+
raise unless e.message == 'not an AF_INET/AF_INET6 sockaddr'
|
163
|
+
end
|
164
|
+
|
153
165
|
private
|
154
166
|
|
155
167
|
def connect
|
156
168
|
@socket = nil
|
157
169
|
exception = nil
|
158
170
|
|
159
|
-
|
171
|
+
if @data[:proxy]
|
160
172
|
family = @data[:proxy][:family] || ::Socket::Constants::AF_UNSPEC
|
161
|
-
|
173
|
+
args = [@data[:proxy][:host], @data[:proxy][:port], family, ::Socket::Constants::SOCK_STREAM]
|
162
174
|
else
|
163
175
|
family = @data[:family] || ::Socket::Constants::AF_UNSPEC
|
164
|
-
|
176
|
+
args = [@data[:host], @data[:port], family, ::Socket::Constants::SOCK_STREAM]
|
165
177
|
end
|
178
|
+
if RUBY_VERSION >= '1.9.2' && defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby'
|
179
|
+
args << nil << nil << false # no reverse lookup
|
180
|
+
end
|
181
|
+
addrinfo = ::Socket.getaddrinfo(*args)
|
166
182
|
|
167
183
|
addrinfo.each do |_, port, _, ip, a_family, s_type|
|
168
184
|
@remote_ip = ip
|
@@ -173,16 +189,23 @@ module Excon
|
|
173
189
|
|
174
190
|
socket = ::Socket.new(a_family, s_type, 0)
|
175
191
|
|
176
|
-
if @
|
177
|
-
socket.
|
178
|
-
|
179
|
-
|
180
|
-
|
192
|
+
if @data[:reuseaddr]
|
193
|
+
socket.setsockopt(::Socket::Constants::SOL_SOCKET, ::Socket::Constants::SO_REUSEADDR, true)
|
194
|
+
if defined?(::Socket::Constants::SO_REUSEPORT)
|
195
|
+
socket.setsockopt(::Socket::Constants::SOL_SOCKET, ::Socket::Constants::SO_REUSEPORT, true)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
begin
|
200
|
+
Timeout.timeout(@data[:connect_timeout]) do
|
201
|
+
if @nonblock
|
202
|
+
socket.connect_nonblock(sockaddr)
|
203
|
+
else
|
181
204
|
socket.connect(sockaddr)
|
182
205
|
end
|
183
|
-
rescue Timeout::Error
|
184
|
-
raise Excon::Errors::Timeout.new('connect timeout reached')
|
185
206
|
end
|
207
|
+
rescue Timeout::Error
|
208
|
+
raise Excon::Errors::Timeout.new('connect timeout reached')
|
186
209
|
end
|
187
210
|
|
188
211
|
@socket = socket
|
data/lib/excon/ssl_socket.rb
CHANGED
@@ -10,8 +10,21 @@ module Excon
|
|
10
10
|
|
11
11
|
# create ssl context
|
12
12
|
ssl_context = OpenSSL::SSL::SSLContext.new
|
13
|
+
|
14
|
+
# disable less secure options, when supported
|
15
|
+
ssl_context_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
|
16
|
+
if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
|
17
|
+
ssl_context_options &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
|
18
|
+
end
|
19
|
+
if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
|
20
|
+
ssl_context_options |= OpenSSL::SSL::OP_NO_COMPRESSION
|
21
|
+
end
|
22
|
+
ssl_context.options = ssl_context_options
|
23
|
+
|
13
24
|
ssl_context.ciphers = @data[:ciphers]
|
14
|
-
|
25
|
+
if @data[:ssl_version]
|
26
|
+
ssl_context.ssl_version = @data[:ssl_version]
|
27
|
+
end
|
15
28
|
if @data[:ssl_verify_peer]
|
16
29
|
# turn verification on
|
17
30
|
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
@@ -74,7 +87,27 @@ module Excon
|
|
74
87
|
# convert Socket to OpenSSL::SSL::SSLSocket
|
75
88
|
@socket = OpenSSL::SSL::SSLSocket.new(@socket, ssl_context)
|
76
89
|
@socket.sync_close = true
|
77
|
-
|
90
|
+
begin
|
91
|
+
Timeout.timeout(@data[:connect_timeout]) do
|
92
|
+
if @nonblock
|
93
|
+
while true
|
94
|
+
begin
|
95
|
+
@socket.connect_nonblock
|
96
|
+
break # connect succeeded
|
97
|
+
rescue OpenSSL::SSL::SSLError => error
|
98
|
+
# would block, rescue and retry as select is non-helpful
|
99
|
+
unless error.message == 'read would block'
|
100
|
+
raise error
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
else
|
105
|
+
@socket.connect
|
106
|
+
end
|
107
|
+
end
|
108
|
+
rescue Timeout::Error
|
109
|
+
raise Excon::Errors::Timeout.new('connect timeout reached')
|
110
|
+
end
|
78
111
|
|
79
112
|
# Server Name Indication (SNI) RFC 3546
|
80
113
|
if @socket.respond_to?(:hostname=)
|
data/lib/excon/utils.rb
CHANGED
@@ -2,7 +2,12 @@ module Excon
|
|
2
2
|
module Utils
|
3
3
|
extend self
|
4
4
|
|
5
|
-
|
5
|
+
control = (0x0..0x1f).map {|c| c.chr }.join + "\x7f"
|
6
|
+
delims = '<>#%"'
|
7
|
+
unwise = '{}|\\^[]`'
|
8
|
+
nonascii = (0x80..0xff).map {|c| c.chr }.join
|
9
|
+
UNESCAPED = /([#{ Regexp.escape(control + ' ' + delims + unwise + nonascii) }])/
|
10
|
+
ESCAPED = /%([0-9a-fA-F]{2})/
|
6
11
|
|
7
12
|
def valid_connection_keys(params = {})
|
8
13
|
Excon::VALID_CONNECTION_KEYS
|
@@ -65,6 +70,14 @@ module Excon
|
|
65
70
|
(?:,\s*|\Z)'xn).flatten
|
66
71
|
end
|
67
72
|
|
73
|
+
# Escapes HTTP reserved and unwise characters in +str+
|
74
|
+
def escape_uri(str)
|
75
|
+
str = str.dup
|
76
|
+
str.force_encoding('BINARY') if FORCE_ENC
|
77
|
+
str.gsub!(UNESCAPED) { "%%%02X" % $1[0].ord }
|
78
|
+
str
|
79
|
+
end
|
80
|
+
|
68
81
|
# Unescapes HTTP reserved and unwise characters in +str+
|
69
82
|
def unescape_uri(str)
|
70
83
|
str = str.dup
|
data/tests/basic_tests.rb
CHANGED
@@ -119,3 +119,72 @@ Shindo.tests('Excon basics (Unix socket)') do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
122
|
+
|
123
|
+
Shindo.tests('Excon basics (reusable local port)') do
|
124
|
+
class CustomSocket < Socket
|
125
|
+
def initialize
|
126
|
+
super(AF_INET, SOCK_STREAM, 0)
|
127
|
+
setsockopt(SOL_SOCKET, SO_REUSEADDR, true)
|
128
|
+
if defined?(SO_REUSEPORT)
|
129
|
+
setsockopt(SOL_SOCKET, SO_REUSEPORT, true)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def bind(address, port)
|
134
|
+
super(Socket.pack_sockaddr_in(port, address))
|
135
|
+
end
|
136
|
+
|
137
|
+
def connect(address, port)
|
138
|
+
super(Socket.pack_sockaddr_in(port, address))
|
139
|
+
end
|
140
|
+
|
141
|
+
def http_get(path)
|
142
|
+
print "GET /content-length/10 HTTP/1.0\r\n\r\n"
|
143
|
+
read.split("\r\n\r\n", 2)[1]
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.ip_address_list
|
147
|
+
if Socket.respond_to?(:ip_address_list)
|
148
|
+
Socket.ip_address_list.select(&:ipv4?).map(&:ip_address)
|
149
|
+
else
|
150
|
+
`ifconfig`.scan(/inet.*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/).flatten
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.find_alternate_ip(ip)
|
155
|
+
ip_address_list.detect {|a| a != ip } || '127.0.0.1'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
with_rackup('basic.ru') do
|
160
|
+
connection = Excon.new("http://127.0.0.1:9292/echo",
|
161
|
+
:reuseaddr => true, # enable address and port reuse
|
162
|
+
:persistent => true # keep the socket open
|
163
|
+
)
|
164
|
+
response = connection.get
|
165
|
+
|
166
|
+
tests('has a local port').returns(true) do
|
167
|
+
response.local_port.to_s =~ /\d{4,5}/ ? true : false
|
168
|
+
end
|
169
|
+
|
170
|
+
tests('local port can be re-bound').returns('x' * 10) do
|
171
|
+
# create a socket with address/port reuse enabled
|
172
|
+
s = CustomSocket.new
|
173
|
+
|
174
|
+
# bind to the same local port and address used in the get above (won't work without reuse options on both sockets)
|
175
|
+
s.bind(response.local_address, response.local_port)
|
176
|
+
|
177
|
+
# connect to the server on a different address than was used for the initial connection to avoid duplicate 5-tuples of: {protcol, src_port, src_addr, dst_port, dst_addr}
|
178
|
+
s.connect(CustomSocket.find_alternate_ip(response.local_address), 9292)
|
179
|
+
|
180
|
+
# send the request
|
181
|
+
body = s.http_get("/content-length/10")
|
182
|
+
|
183
|
+
# close both the sockets
|
184
|
+
s.close
|
185
|
+
connection.reset
|
186
|
+
|
187
|
+
body
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Shindo.tests('Excon Decompress Middleware') do
|
2
|
+
env_init
|
3
|
+
with_rackup('basic.ru') do
|
4
|
+
tests('encoded uri passed to connection') do
|
5
|
+
tests('GET /echo%20dirty').returns(200) do
|
6
|
+
connection = Excon::Connection.new({
|
7
|
+
:host => '127.0.0.1',
|
8
|
+
:middlewares => Excon.defaults[:middlewares] + [Excon::Middleware::EscapePath],
|
9
|
+
:nonblock => false,
|
10
|
+
:port => 9292,
|
11
|
+
:scheme => 'http',
|
12
|
+
:ssl_verify_peer => false
|
13
|
+
})
|
14
|
+
response = connection.request(:method => :get, :path => '/echo%20dirty')
|
15
|
+
response[:status]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
tests('unencoded uri passed to connection') do
|
20
|
+
tests('GET /echo dirty').returns(200) do
|
21
|
+
connection = Excon::Connection.new({
|
22
|
+
:host => '127.0.0.1',
|
23
|
+
:middlewares => Excon.defaults[:middlewares] + [Excon::Middleware::EscapePath],
|
24
|
+
:nonblock => false,
|
25
|
+
:port => 9292,
|
26
|
+
:scheme => 'http',
|
27
|
+
:ssl_verify_peer => false
|
28
|
+
})
|
29
|
+
response = connection.request(:method => :get, :path => '/echo dirty')
|
30
|
+
response[:status]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/tests/rackups/basic.rb
CHANGED
data/tests/servers/good.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.32.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- dpiddy (Dan Peterson)
|
@@ -11,12 +10,11 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date:
|
13
|
+
date: 2014-02-27 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: activesupport
|
18
17
|
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
18
|
requirements:
|
21
19
|
- - ! '>='
|
22
20
|
- !ruby/object:Gem::Version
|
@@ -24,7 +22,6 @@ dependencies:
|
|
24
22
|
type: :development
|
25
23
|
prerelease: false
|
26
24
|
version_requirements: !ruby/object:Gem::Requirement
|
27
|
-
none: false
|
28
25
|
requirements:
|
29
26
|
- - ! '>='
|
30
27
|
- !ruby/object:Gem::Version
|
@@ -32,7 +29,6 @@ dependencies:
|
|
32
29
|
- !ruby/object:Gem::Dependency
|
33
30
|
name: delorean
|
34
31
|
requirement: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
32
|
requirements:
|
37
33
|
- - ! '>='
|
38
34
|
- !ruby/object:Gem::Version
|
@@ -40,7 +36,6 @@ dependencies:
|
|
40
36
|
type: :development
|
41
37
|
prerelease: false
|
42
38
|
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
39
|
requirements:
|
45
40
|
- - ! '>='
|
46
41
|
- !ruby/object:Gem::Version
|
@@ -48,7 +43,6 @@ dependencies:
|
|
48
43
|
- !ruby/object:Gem::Dependency
|
49
44
|
name: eventmachine
|
50
45
|
requirement: !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
46
|
requirements:
|
53
47
|
- - ! '>='
|
54
48
|
- !ruby/object:Gem::Version
|
@@ -56,7 +50,6 @@ dependencies:
|
|
56
50
|
type: :development
|
57
51
|
prerelease: false
|
58
52
|
version_requirements: !ruby/object:Gem::Requirement
|
59
|
-
none: false
|
60
53
|
requirements:
|
61
54
|
- - ! '>='
|
62
55
|
- !ruby/object:Gem::Version
|
@@ -64,7 +57,6 @@ dependencies:
|
|
64
57
|
- !ruby/object:Gem::Dependency
|
65
58
|
name: open4
|
66
59
|
requirement: !ruby/object:Gem::Requirement
|
67
|
-
none: false
|
68
60
|
requirements:
|
69
61
|
- - ! '>='
|
70
62
|
- !ruby/object:Gem::Version
|
@@ -72,7 +64,6 @@ dependencies:
|
|
72
64
|
type: :development
|
73
65
|
prerelease: false
|
74
66
|
version_requirements: !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
67
|
requirements:
|
77
68
|
- - ! '>='
|
78
69
|
- !ruby/object:Gem::Version
|
@@ -80,7 +71,6 @@ dependencies:
|
|
80
71
|
- !ruby/object:Gem::Dependency
|
81
72
|
name: rake
|
82
73
|
requirement: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
74
|
requirements:
|
85
75
|
- - ! '>='
|
86
76
|
- !ruby/object:Gem::Version
|
@@ -88,7 +78,6 @@ dependencies:
|
|
88
78
|
type: :development
|
89
79
|
prerelease: false
|
90
80
|
version_requirements: !ruby/object:Gem::Requirement
|
91
|
-
none: false
|
92
81
|
requirements:
|
93
82
|
- - ! '>='
|
94
83
|
- !ruby/object:Gem::Version
|
@@ -96,7 +85,6 @@ dependencies:
|
|
96
85
|
- !ruby/object:Gem::Dependency
|
97
86
|
name: rdoc
|
98
87
|
requirement: !ruby/object:Gem::Requirement
|
99
|
-
none: false
|
100
88
|
requirements:
|
101
89
|
- - ! '>='
|
102
90
|
- !ruby/object:Gem::Version
|
@@ -104,7 +92,6 @@ dependencies:
|
|
104
92
|
type: :development
|
105
93
|
prerelease: false
|
106
94
|
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
none: false
|
108
95
|
requirements:
|
109
96
|
- - ! '>='
|
110
97
|
- !ruby/object:Gem::Version
|
@@ -112,7 +99,6 @@ dependencies:
|
|
112
99
|
- !ruby/object:Gem::Dependency
|
113
100
|
name: shindo
|
114
101
|
requirement: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
102
|
requirements:
|
117
103
|
- - ! '>='
|
118
104
|
- !ruby/object:Gem::Version
|
@@ -120,7 +106,6 @@ dependencies:
|
|
120
106
|
type: :development
|
121
107
|
prerelease: false
|
122
108
|
version_requirements: !ruby/object:Gem::Requirement
|
123
|
-
none: false
|
124
109
|
requirements:
|
125
110
|
- - ! '>='
|
126
111
|
- !ruby/object:Gem::Version
|
@@ -128,7 +113,6 @@ dependencies:
|
|
128
113
|
- !ruby/object:Gem::Dependency
|
129
114
|
name: sinatra
|
130
115
|
requirement: !ruby/object:Gem::Requirement
|
131
|
-
none: false
|
132
116
|
requirements:
|
133
117
|
- - ! '>='
|
134
118
|
- !ruby/object:Gem::Version
|
@@ -136,7 +120,6 @@ dependencies:
|
|
136
120
|
type: :development
|
137
121
|
prerelease: false
|
138
122
|
version_requirements: !ruby/object:Gem::Requirement
|
139
|
-
none: false
|
140
123
|
requirements:
|
141
124
|
- - ! '>='
|
142
125
|
- !ruby/object:Gem::Version
|
@@ -148,8 +131,11 @@ extensions: []
|
|
148
131
|
extra_rdoc_files:
|
149
132
|
- README.md
|
150
133
|
files:
|
134
|
+
- CONTRIBUTING.md
|
135
|
+
- CONTRIBUTORS.md
|
151
136
|
- Gemfile
|
152
137
|
- Gemfile.lock
|
138
|
+
- LICENSE.md
|
153
139
|
- README.md
|
154
140
|
- Rakefile
|
155
141
|
- benchmarks/class_vs_lambda.rb
|
@@ -179,6 +165,7 @@ files:
|
|
179
165
|
- lib/excon/errors.rb
|
180
166
|
- lib/excon/middlewares/base.rb
|
181
167
|
- lib/excon/middlewares/decompress.rb
|
168
|
+
- lib/excon/middlewares/escape_path.rb
|
182
169
|
- lib/excon/middlewares/expects.rb
|
183
170
|
- lib/excon/middlewares/idempotent.rb
|
184
171
|
- lib/excon/middlewares/instrumentor.rb
|
@@ -201,6 +188,7 @@ files:
|
|
201
188
|
- tests/header_tests.rb
|
202
189
|
- tests/middlewares/canned_response_tests.rb
|
203
190
|
- tests/middlewares/decompress_tests.rb
|
191
|
+
- tests/middlewares/escape_path_tests.rb
|
204
192
|
- tests/middlewares/idempotent_tests.rb
|
205
193
|
- tests/middlewares/instrumentation_tests.rb
|
206
194
|
- tests/middlewares/mock_tests.rb
|
@@ -237,29 +225,25 @@ files:
|
|
237
225
|
homepage: https://github.com/geemus/excon
|
238
226
|
licenses:
|
239
227
|
- MIT
|
228
|
+
metadata: {}
|
240
229
|
post_install_message:
|
241
230
|
rdoc_options:
|
242
231
|
- --charset=UTF-8
|
243
232
|
require_paths:
|
244
233
|
- lib
|
245
234
|
required_ruby_version: !ruby/object:Gem::Requirement
|
246
|
-
none: false
|
247
235
|
requirements:
|
248
236
|
- - ! '>='
|
249
237
|
- !ruby/object:Gem::Version
|
250
238
|
version: '0'
|
251
|
-
segments:
|
252
|
-
- 0
|
253
|
-
hash: -1399644688570873046
|
254
239
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
255
|
-
none: false
|
256
240
|
requirements:
|
257
241
|
- - ! '>='
|
258
242
|
- !ruby/object:Gem::Version
|
259
243
|
version: '0'
|
260
244
|
requirements: []
|
261
245
|
rubyforge_project: excon
|
262
|
-
rubygems_version:
|
246
|
+
rubygems_version: 2.2.2
|
263
247
|
signing_key:
|
264
248
|
specification_version: 2
|
265
249
|
summary: speed, persistence, http(s)
|