excon 0.6.6 → 0.7.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.

@@ -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.6.6'
17
- s.date = '2011-09-06'
16
+ s.version = '0.7.0'
17
+ s.date = '2011-09-12'
18
18
  s.rubyforge_project = 'excon'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -90,6 +90,7 @@ Gem::Specification.new do |s|
90
90
  lib/excon/constants.rb
91
91
  lib/excon/errors.rb
92
92
  lib/excon/response.rb
93
+ lib/excon/socket.rb
93
94
  tests/basic_tests.rb
94
95
  tests/header_tests.rb
95
96
  tests/idempotent_tests.rb
@@ -2,6 +2,7 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  require 'cgi'
5
+ require 'forwardable'
5
6
  require 'openssl'
6
7
  require 'rbconfig'
7
8
  require 'socket'
@@ -11,6 +12,7 @@ require 'excon/constants'
11
12
  require 'excon/connection'
12
13
  require 'excon/errors'
13
14
  require 'excon/response'
15
+ require 'excon/socket'
14
16
 
15
17
  module Excon
16
18
  class << self
@@ -20,13 +20,16 @@ module Excon
20
20
  def initialize(url, params = {})
21
21
  uri = URI.parse(url)
22
22
  @connection = {
23
- :headers => {},
24
- :host => uri.host,
25
- :mock => Excon.mock,
26
- :path => uri.path,
27
- :port => uri.port.to_s,
28
- :query => uri.query,
29
- :scheme => uri.scheme
23
+ :connect_timeout => 60,
24
+ :headers => {},
25
+ :host => uri.host,
26
+ :mock => Excon.mock,
27
+ :path => uri.path,
28
+ :port => uri.port.to_s,
29
+ :query => uri.query,
30
+ :read_timeout => 60,
31
+ :scheme => uri.scheme,
32
+ :write_timeout => 60
30
33
  }.merge!(params)
31
34
 
32
35
  # use proxy from the environment if present
@@ -36,7 +39,7 @@ module Excon
36
39
  @proxy = setup_proxy(params[:proxy])
37
40
  end
38
41
 
39
- if https?
42
+ if @connection[:scheme] == 'https'
40
43
  # use https_proxy if that has been specified
41
44
  if ENV.has_key?('https_proxy')
42
45
  @proxy = setup_proxy(ENV['https_proxy'])
@@ -157,7 +160,6 @@ module Excon
157
160
 
158
161
  # write out the request, sans body
159
162
  socket.write(request)
160
- socket.flush
161
163
 
162
164
  # write out the body
163
165
  if params[:body]
@@ -223,85 +225,15 @@ module Excon
223
225
  end
224
226
 
225
227
  private
226
- def connect
227
- new_socket = open_socket
228
-
229
- if https?
230
- # create ssl context
231
- ssl_context = OpenSSL::SSL::SSLContext.new
232
-
233
- if Excon.ssl_verify_peer
234
- # turn verification on
235
- ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
236
-
237
- if Excon.ssl_ca_path
238
- ssl_context.ca_path = Excon.ssl_ca_path
239
- else
240
- # use default cert store
241
- store = OpenSSL::X509::Store.new
242
- store.set_default_paths
243
- ssl_context.cert_store = store
244
- end
245
- else
246
- # turn verification off
247
- ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
248
- end
249
-
250
- if @connection.has_key?(:client_cert) && @connection.has_key?(:client_key)
251
- ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@connection[:client_cert]))
252
- ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@connection[:client_key]))
253
- end
254
-
255
- new_socket = open_ssl_socket(new_socket, ssl_context)
256
- end
257
-
258
- new_socket
259
- end
260
-
261
- def open_ssl_socket(socket, ssl_context)
262
-
263
- new_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
264
- new_socket.sync_close = true
265
-
266
- if @proxy
267
- new_socket << "CONNECT " << @connection[:host] << ":" << @connection[:port] << HTTP_1_1
268
- new_socket << "Host: " << @connection[:host] << ":" << @connection[:port] << CR_NL << CR_NL
269
-
270
- # eat the proxy's connection response
271
- while line = new_socket.readline.strip
272
- break if line.empty?
273
- end
274
- end
275
-
276
- new_socket.connect
277
- # verify connection
278
- if Excon.ssl_verify_peer
279
- new_socket.post_connection_check(@connection[:host])
280
- end
281
- new_socket
282
- end
283
-
284
- def open_socket
285
- if @proxy
286
- socket = TCPSocket.open(@proxy[:host], @proxy[:port])
287
- else
288
- socket = TCPSocket.open(@connection[:host], @connection[:port])
289
- end
290
- socket
291
- end
292
228
 
293
229
  def socket
294
- sockets[@socket_key] ||= connect
230
+ sockets[@socket_key] ||= Excon::Socket.new(@connection, @proxy)
295
231
  end
296
232
 
297
233
  def sockets
298
234
  Thread.current[:_excon_sockets] ||= {}
299
235
  end
300
236
 
301
- def https?
302
- @connection[:scheme] == 'https'
303
- end
304
-
305
237
  def setup_proxy(proxy)
306
238
  uri = URI.parse(proxy)
307
239
  unless uri.host and uri.port and uri.scheme
@@ -1,6 +1,6 @@
1
1
  module Excon
2
2
  unless const_defined?(:VERSION)
3
- VERSION = '0.6.6'
3
+ VERSION = '0.7.0'
4
4
  end
5
5
 
6
6
  unless const_defined?(:CHUNK_SIZE)
@@ -0,0 +1,114 @@
1
+ module Excon
2
+ class Socket
3
+
4
+ extend Forwardable
5
+
6
+ def_delegators(:@socket, :close, :close)
7
+ def_delegators(:@socket, :readline, :readline)
8
+
9
+ def initialize(connection_params = {}, proxy = {})
10
+ @connection_params, @proxy = connection_params, proxy
11
+ @read_buffer, @write_buffer = '', ''
12
+
13
+ @socket = ::Socket.new(::Socket::Constants::AF_INET, ::Socket::Constants::SOCK_STREAM, 0)
14
+
15
+ # nonblocking connect
16
+ if @proxy
17
+ sockaddr = ::Socket.sockaddr_in(@proxy[:port], @proxy[:host])
18
+ else
19
+ sockaddr = ::Socket.sockaddr_in(@connection_params[:port], @connection_params[:host])
20
+ end
21
+ begin
22
+ @socket.connect_nonblock(sockaddr)
23
+ rescue Errno::EINPROGRESS
24
+ IO.select(nil, [@socket], nil, @connection_params[:connect_timeout])
25
+ begin
26
+ @socket.connect_nonblock(sockaddr)
27
+ rescue Errno::EISCONN
28
+ end
29
+ end
30
+
31
+ # ssl setup
32
+ if @connection_params[:scheme] == 'https'
33
+ # create ssl context
34
+ ssl_context = OpenSSL::SSL::SSLContext.new
35
+
36
+ if Excon.ssl_verify_peer
37
+ # turn verification on
38
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
39
+
40
+ if Excon.ssl_ca_path
41
+ ssl_context.ca_path = Excon.ssl_ca_path
42
+ else
43
+ # use default cert store
44
+ store = OpenSSL::X509::Store.new
45
+ store.set_default_paths
46
+ ssl_context.cert_store = store
47
+ end
48
+ else
49
+ # turn verification off
50
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
51
+ end
52
+
53
+ if @connection_params.has_key?(:client_cert) && @connection_params.has_key?(:client_key)
54
+ ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@connection_params[:client_cert]))
55
+ ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@connection_params[:client_key]))
56
+ end
57
+
58
+ @socket = OpenSSL::SSL::SSLSocket.new(@socket, ssl_context)
59
+ @socket.sync_close = true
60
+
61
+ if @proxy
62
+ @socket << "CONNECT " << @connection_params[:host] << ":" << @connection_params[:port] << HTTP_1_1
63
+ @socket << "Host: " << @connection_params[:host] << ":" << @connection_params[:port] << CR_NL << CR_NL
64
+
65
+ # eat the proxy's connection response
66
+ while line = @socket.readline.strip
67
+ break if line.empty?
68
+ end
69
+ end
70
+ end
71
+
72
+ if @connection_params[:scheme] == 'https'
73
+ # verify connection
74
+ if Excon.ssl_verify_peer
75
+ @socket.post_connection_check(@connection_params[:host])
76
+ end
77
+ end
78
+
79
+ @socket
80
+ end
81
+
82
+ def read(max_length)
83
+ begin
84
+ until @read_buffer.length >= max_length
85
+ @read_buffer << @socket.read_nonblock(max_length)
86
+ end
87
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
88
+ if IO.select([@socket], nil, nil, @connection_params[:read_timeout])
89
+ retry
90
+ else
91
+ raise(Timeout::Error)
92
+ end
93
+ end
94
+ @read_buffer.slice!(0, max_length)
95
+ end
96
+
97
+ def write(data)
98
+ @write_buffer << data
99
+ until @write_buffer.empty?
100
+ begin
101
+ max_length = [@write_buffer.length, Excon::CHUNK_SIZE].min
102
+ @socket.write_nonblock(@write_buffer.slice!(0, max_length))
103
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
104
+ if IO.select(nil [@socket], nil, @connection_params[:write_timeout])
105
+ retry
106
+ else
107
+ raise(Timeout::Error)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ end
114
+ end
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: 11
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 6
9
- - 6
10
- version: 0.6.6
8
+ - 7
9
+ - 0
10
+ version: 0.7.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-09-06 00:00:00 Z
18
+ date: 2011-09-12 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: open4
@@ -111,6 +111,7 @@ files:
111
111
  - lib/excon/constants.rb
112
112
  - lib/excon/errors.rb
113
113
  - lib/excon/response.rb
114
+ - lib/excon/socket.rb
114
115
  - tests/basic_tests.rb
115
116
  - tests/header_tests.rb
116
117
  - tests/idempotent_tests.rb