excon 0.5.8 → 0.6.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/README.rdoc +4 -1
- data/changelog.txt +7 -0
- data/excon.gemspec +4 -2
- data/lib/excon.rb +1 -1
- data/lib/excon/connection.rb +39 -12
- data/lib/excon/errors.rb +2 -0
- data/lib/excon/response.rb +1 -1
- data/tests/proxy_tests.rb +64 -0
- data/tests/query_string_tests.rb +4 -4
- data/tests/rackups/proxy.ru +12 -0
- metadata +7 -5
data/README.rdoc
CHANGED
@@ -27,7 +27,10 @@ Both one off and persistent connections also support many other options, for exa
|
|
27
27
|
|
28
28
|
You can also stream responses by passing a block that will receive each chunk.
|
29
29
|
|
30
|
-
Excon.get('http://geemus.com')
|
30
|
+
Excon.get('http://geemus.com') do |chunk, remaining_bytes, total_bytes|
|
31
|
+
puts chunk
|
32
|
+
puts "Remaining: #{remaining_bytes.to_f / total_bytes}%"
|
33
|
+
end
|
31
34
|
|
32
35
|
These options can be combined to make pretty much any request you might need.
|
33
36
|
|
data/changelog.txt
CHANGED
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 = '2011-03-
|
16
|
+
s.version = '0.6.0'
|
17
|
+
s.date = '2011-03-30'
|
18
18
|
s.rubyforge_project = 'excon'
|
19
19
|
|
20
20
|
## Make sure your summary is short. The description may be as long
|
@@ -89,8 +89,10 @@ Gem::Specification.new do |s|
|
|
89
89
|
lib/excon/errors.rb
|
90
90
|
lib/excon/response.rb
|
91
91
|
tests/basic_tests.rb
|
92
|
+
tests/proxy_tests.rb
|
92
93
|
tests/query_string_tests.rb
|
93
94
|
tests/rackups/basic.ru
|
95
|
+
tests/rackups/proxy.ru
|
94
96
|
tests/rackups/query_string.ru
|
95
97
|
tests/rackups/thread_safety.ru
|
96
98
|
tests/stub_tests.rb
|
data/lib/excon.rb
CHANGED
data/lib/excon/connection.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Excon
|
2
2
|
class Connection
|
3
|
-
attr_reader :connection
|
3
|
+
attr_reader :connection, :proxy
|
4
4
|
|
5
5
|
CR_NL = "\r\n"
|
6
6
|
HTTP_1_1 = " HTTP/1.1\r\n"
|
@@ -16,18 +16,23 @@ module Excon
|
|
16
16
|
# @option params [Fixnum] :port The port on which to connect, to the destination host
|
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
|
+
# @option params [String] :proxy Proxy server; e.g. 'http://myproxy.com:8888'
|
19
20
|
def initialize(url, params = {})
|
20
21
|
uri = URI.parse(url)
|
21
22
|
@connection = {
|
22
23
|
:headers => {},
|
23
24
|
:host => uri.host,
|
24
25
|
:path => uri.path,
|
25
|
-
:port => uri.port,
|
26
|
+
:port => uri.port.to_s,
|
26
27
|
:query => uri.query,
|
27
28
|
:scheme => uri.scheme
|
28
29
|
}.merge!(params)
|
29
30
|
|
30
|
-
|
31
|
+
if params.has_key?(:proxy)
|
32
|
+
@connection[:headers]['Proxy-Connection'] ||= 'Keep-Alive'
|
33
|
+
setup_proxy(params[:proxy])
|
34
|
+
end
|
35
|
+
@socket_key = '' << @connection[:host] << ':' << @connection[:port]
|
31
36
|
reset
|
32
37
|
end
|
33
38
|
|
@@ -46,7 +51,7 @@ module Excon
|
|
46
51
|
# connection has defaults, merge in new params to override
|
47
52
|
params = @connection.merge(params)
|
48
53
|
params[:headers] = @connection[:headers].merge(params[:headers] || {})
|
49
|
-
params[:headers]['Host'] ||= '' << params[:host] << ':' << params[:port]
|
54
|
+
params[:headers]['Host'] ||= '' << params[:host] << ':' << params[:port]
|
50
55
|
|
51
56
|
# if path is empty or doesn't start with '/', insert one
|
52
57
|
unless params[:path][0, 1] == '/'
|
@@ -64,7 +69,11 @@ module Excon
|
|
64
69
|
end
|
65
70
|
|
66
71
|
# start with "METHOD /path"
|
67
|
-
request = params[:method].to_s.upcase << ' '
|
72
|
+
request = params[:method].to_s.upcase << ' '
|
73
|
+
if @proxy
|
74
|
+
request << params[:scheme] << '://' << params[:host] << ':' << params[:port]
|
75
|
+
end
|
76
|
+
request << params[:path]
|
68
77
|
|
69
78
|
# add query to path, if there is one
|
70
79
|
case params[:query]
|
@@ -73,15 +82,12 @@ module Excon
|
|
73
82
|
when Hash
|
74
83
|
request << '?'
|
75
84
|
for key, values in params[:query]
|
76
|
-
|
77
|
-
when nil
|
85
|
+
if values.nil?
|
78
86
|
request << key.to_s << '&'
|
79
|
-
|
80
|
-
|
87
|
+
else
|
88
|
+
for value in [*values]
|
81
89
|
request << key.to_s << '=' << CGI.escape(value.to_s) << '&'
|
82
90
|
end
|
83
|
-
else
|
84
|
-
request << key.to_s << '=' << CGI.escape(values.to_s) << '&'
|
85
91
|
end
|
86
92
|
end
|
87
93
|
request.chop! # remove trailing '&'
|
@@ -180,7 +186,7 @@ module Excon
|
|
180
186
|
|
181
187
|
private
|
182
188
|
def connect
|
183
|
-
new_socket =
|
189
|
+
new_socket = open_socket
|
184
190
|
|
185
191
|
if @connection[:scheme] == 'https'
|
186
192
|
# create ssl context
|
@@ -219,6 +225,15 @@ module Excon
|
|
219
225
|
|
220
226
|
new_socket
|
221
227
|
end
|
228
|
+
|
229
|
+
def open_socket
|
230
|
+
if @proxy
|
231
|
+
socket = TCPSocket.open(@proxy[:host], @proxy[:port])
|
232
|
+
else
|
233
|
+
socket = TCPSocket.open(@connection[:host], @connection[:port])
|
234
|
+
end
|
235
|
+
socket
|
236
|
+
end
|
222
237
|
|
223
238
|
def socket
|
224
239
|
sockets[@socket_key] ||= connect
|
@@ -227,6 +242,18 @@ module Excon
|
|
227
242
|
def sockets
|
228
243
|
Thread.current[:_excon_sockets] ||= {}
|
229
244
|
end
|
245
|
+
|
246
|
+
def setup_proxy(proxy)
|
247
|
+
uri = URI.parse(proxy)
|
248
|
+
unless uri.host and uri.port and uri.scheme
|
249
|
+
raise Excon::Errors::ProxyParseError, "Proxy is invalid"
|
250
|
+
end
|
251
|
+
@proxy = {
|
252
|
+
:host => uri.host,
|
253
|
+
:port => uri.port,
|
254
|
+
:scheme => uri.scheme
|
255
|
+
}
|
256
|
+
end
|
230
257
|
|
231
258
|
end
|
232
259
|
end
|
data/lib/excon/errors.rb
CHANGED
data/lib/excon/response.rb
CHANGED
@@ -44,7 +44,7 @@ module Excon
|
|
44
44
|
else
|
45
45
|
remaining = content_length
|
46
46
|
while remaining > 0
|
47
|
-
yield socket.read([CHUNK_SIZE, remaining].min)
|
47
|
+
yield socket.read([CHUNK_SIZE, remaining].min), [remaining - CHUNK_SIZE, 0].max, content_length
|
48
48
|
remaining -= CHUNK_SIZE
|
49
49
|
end
|
50
50
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'test_helper'))
|
2
|
+
|
3
|
+
Shindo.tests('Excon proxy support') do
|
4
|
+
|
5
|
+
tests('proxy configuration') do
|
6
|
+
|
7
|
+
tests('no proxy') do
|
8
|
+
connection = Excon.new('http://foo.com')
|
9
|
+
|
10
|
+
tests('connection.proxy').returns(nil) do
|
11
|
+
connection.proxy
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
tests('with fully-specified proxy: https://myproxy.net:8080') do
|
16
|
+
connection = Excon.new('http://foo.com', :proxy => 'https://myproxy.net:8080')
|
17
|
+
|
18
|
+
tests('connection.proxy.host').returns('myproxy.net') do
|
19
|
+
connection.proxy[:host]
|
20
|
+
end
|
21
|
+
|
22
|
+
tests('connection.proxy.port').returns(8080) do
|
23
|
+
connection.proxy[:port]
|
24
|
+
end
|
25
|
+
|
26
|
+
tests('connection.proxy.scheme').returns('https') do
|
27
|
+
connection.proxy[:scheme]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
with_rackup('proxy.ru') do
|
34
|
+
|
35
|
+
tests('http proxying: http://foo.com:8080') do
|
36
|
+
connection = Excon.new('http://foo.com:8080', :proxy => 'http://localhost:9292')
|
37
|
+
response = connection.request(:method => :get, :path => '/bar', :query => {:alpha => 'kappa'})
|
38
|
+
|
39
|
+
tests('response.status').returns(200) do
|
40
|
+
response.status
|
41
|
+
end
|
42
|
+
|
43
|
+
# must be absolute form for proxy requests
|
44
|
+
tests('sent Request URI').returns('http://foo.com:8080/bar?alpha=kappa') do
|
45
|
+
response.headers['Sent-Request-Uri']
|
46
|
+
end
|
47
|
+
|
48
|
+
tests('sent Host header').returns('foo.com:8080') do
|
49
|
+
response.headers['Sent-Host']
|
50
|
+
end
|
51
|
+
|
52
|
+
tests('sent Proxy-Connection header').returns('Keep-Alive') do
|
53
|
+
response.headers['Sent-Proxy-Connection']
|
54
|
+
end
|
55
|
+
|
56
|
+
tests('response.body (proxied content)').returns('proxied content') do
|
57
|
+
response.body
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
data/tests/query_string_tests.rb
CHANGED
@@ -31,11 +31,11 @@ with_rackup('query_string.ru') do
|
|
31
31
|
response = connection.request(:method => :get, :path => '/query', :query => {:foo => 'bar', :me => nil})
|
32
32
|
query_string = response.body[7..-1] # query string sent
|
33
33
|
|
34
|
-
|
34
|
+
test("query string sent includes 'foo=bar'") do
|
35
35
|
query_string.split('&').include?('foo=bar')
|
36
36
|
end
|
37
37
|
|
38
|
-
|
38
|
+
test("query string sent includes 'me'") do
|
39
39
|
query_string.split('&').include?('me')
|
40
40
|
end
|
41
41
|
|
@@ -46,11 +46,11 @@ with_rackup('query_string.ru') do
|
|
46
46
|
response = connection.request(:method => :get, :path => '/query', :query => {:foo => 'bar', :me => 'too'})
|
47
47
|
query_string = response.body[7..-1] # query string sent
|
48
48
|
|
49
|
-
|
49
|
+
test("query string sent includes 'foo=bar'") do
|
50
50
|
query_string.split('&').include?('foo=bar')
|
51
51
|
end
|
52
52
|
|
53
|
-
|
53
|
+
test("query string sent includes 'me=too'") do
|
54
54
|
query_string.split('&').include?('me=too')
|
55
55
|
end
|
56
56
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
|
3
|
+
class App < Sinatra::Base
|
4
|
+
get '/bar' do
|
5
|
+
headers "Sent-Request-Uri" => request.env['REQUEST_URI'].to_s,
|
6
|
+
"Sent-Host" => request.env['HTTP_HOST'].to_s,
|
7
|
+
"Sent-Proxy-Connection" => request.env['HTTP_PROXY_CONNECTION'].to_s
|
8
|
+
'proxied content'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
run App
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: excon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 6
|
9
|
+
- 0
|
10
|
+
version: 0.6.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- geemus (Wesley Beary)
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-03-
|
18
|
+
date: 2011-03-30 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -111,8 +111,10 @@ files:
|
|
111
111
|
- lib/excon/errors.rb
|
112
112
|
- lib/excon/response.rb
|
113
113
|
- tests/basic_tests.rb
|
114
|
+
- tests/proxy_tests.rb
|
114
115
|
- tests/query_string_tests.rb
|
115
116
|
- tests/rackups/basic.ru
|
117
|
+
- tests/rackups/proxy.ru
|
116
118
|
- tests/rackups/query_string.ru
|
117
119
|
- tests/rackups/thread_safety.ru
|
118
120
|
- tests/stub_tests.rb
|