aws-sdk 1.6.2 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,7 +13,6 @@
13
13
 
14
14
  module AWS
15
15
  class SimpleEmailService
16
-
17
16
  # @private
18
17
  class Request < Core::Http::Request
19
18
 
@@ -24,6 +23,5 @@ module AWS
24
23
  end
25
24
 
26
25
  end
27
-
28
26
  end
29
27
  end
@@ -19,9 +19,6 @@ module AWS
19
19
 
20
20
  include Core::Signature::Version3
21
21
 
22
- # @return [String,nil]
23
- attr_accessor :body
24
-
25
22
  def read_timeout
26
23
  # increase read timeout for long polling
27
24
  if headers['x-amz-target'] =~ /PollFor(Decision|Activity)Task/
@@ -16,18 +16,19 @@ require 'net/http/connection_pool/connection'
16
16
  require 'thread'
17
17
  require 'logger'
18
18
 
19
+ # A wrapper around Net::HTTP that provides a manged pool of persistant HTTP
20
+ # connections.
21
+ #
22
+ # pool = Net::HTTP::ConnectionPool.new
23
+ # connection = pool.connection_for('domain.com')
24
+ # connection.request(Net::HTTP::Get.new('/')) do |resp|
25
+ # # Connection#request yields Net::HTTPResponse objects
26
+ # puts resp.body
27
+ # end
28
+ #
19
29
  # @private
20
30
  class Net::HTTP::ConnectionPool
21
31
 
22
- SOCKET_ERRORS = [
23
- EOFError,
24
- IOError,
25
- Errno::ECONNABORTED,
26
- Errno::ECONNRESET,
27
- Errno::EPIPE,
28
- Errno::EINVAL
29
- ]
30
-
31
32
  # @param [Hash] options
32
33
  #
33
34
  # @option options [Numeric] :http_idle_timeout (60) The number of seconds a
@@ -42,10 +43,10 @@ class Net::HTTP::ConnectionPool
42
43
  #
43
44
  # @option options [Logger] :logger (Logger.new($stdout)) Where debug out
44
45
  # is sent (wire traces).
45
- #
46
+ #
46
47
  def initialize options = {}
47
- @pool = []
48
48
  @pool_mutex = Mutex.new
49
+ @pool = []
49
50
  @open_timeout = options[:http_open_timeout] || 15
50
51
  @idle_timeout = options[:http_idle_timeout] || 60
51
52
  @http_wire_trace = !!options[:http_wire_trace]
@@ -56,7 +57,7 @@ class Net::HTTP::ConnectionPool
56
57
  end
57
58
  end
58
59
 
59
- # @return [Integer]
60
+ # @return [Integer]
60
61
  attr_reader :idle_timeout
61
62
 
62
63
  # @return [Integer]
@@ -76,20 +77,18 @@ class Net::HTTP::ConnectionPool
76
77
  # Requests a connection object from the connection pool.
77
78
  #
78
79
  # connection = pool.connection_for('domain.com')
79
- # connection.request(Net::HTTP::Get.new('/index.html'))
80
- # connection.request(Net::HTTP::Get.new('/about.html'))
80
+ # connection.request(Net::HTTP::Get.new('/index.html')) {|resp|}
81
+ # connection.request(Net::HTTP::Get.new('/about.html')) {|resp|}
81
82
  #
82
83
  # # same thing in block form
83
84
  # pool.connection_for('domain.com') do |connection|
84
- # connection.request(Net::HTTP::Get.new('/index.html'))
85
- # connection.request(Net::HTTP::Get.new('/about.html'))
85
+ # connection.request(Net::HTTP::Get.new('/index.html')) {|resp|}
86
+ # connection.request(Net::HTTP::Get.new('/about.html')) {|resp|}
86
87
  # end
87
88
  #
88
89
  # Because the pool manages HTTP sessions you do not have to
89
90
  # worry about closing a connection or returning a connection
90
- # to the pool. Every time you call request on a connection
91
- # object, a HTTP session received from the pool and returned after
92
- # the request is complete.
91
+ # to the pool.
93
92
  #
94
93
  # @param [String] host
95
94
  #
@@ -102,12 +101,12 @@ class Net::HTTP::ConnectionPool
102
101
  # SSL. Defaults to +false+, unless +:port+ is 443, then it defaults
103
102
  # to +true+.
104
103
  #
105
- # @option options [Boolean] :ssl_verify_peer (true) If true, ssl
104
+ # @option options [Boolean] :ssl_verify_peer (true) If true, ssl
106
105
  # connections should verify peer certificates. This should only ever be
107
106
  # set false false for debugging purposes.
108
107
  #
109
108
  # @option options [String] :ssl_ca_file Full path to the SSL certificate
110
- # authority bundle file that should be used when verifying peer
109
+ # authority bundle file that should be used when verifying peer
111
110
  # certificates. If you do not pass +:ssl_ca_file+ or +:ssl_ca_path+
112
111
  # the the system default will be used if available.
113
112
  #
@@ -117,7 +116,7 @@ class Net::HTTP::ConnectionPool
117
116
  # the the system default will be used if available.
118
117
  #
119
118
  # @option options [URI::HTTP,String] :proxy_uri (nil) A URI string or
120
- # URI::HTTP object to use as a proxy. You should not provide
119
+ # URI::HTTP object to use as a proxy. You should not provide
121
120
  # +:proxy_uri+ with any other proxy options.
122
121
  #
123
122
  # :proxy_uri => 'http://user:pass@host.com:80'
@@ -142,54 +141,19 @@ class Net::HTTP::ConnectionPool
142
141
  connection
143
142
  end
144
143
 
145
- # @private
146
- def request connection, *request_args, &block
147
-
148
- session = nil
149
- response = nil
150
- retried = false
151
-
152
- begin
153
-
154
- session = session_for(connection, retried)
155
- session.http_session.read_timeout = connection.read_timeout
156
- response = session.request(*request_args, &block)
157
-
158
- rescue Exception => error
159
-
160
- # close the http session to prevent the connection from being
161
- # left open and risk the other side sending data
162
- session.finish if session
163
-
164
- # retry socket errors once on a new session
165
- if SOCKET_ERRORS.include?(error.class) and !retried
166
- retried = true
167
- retry
168
- end
169
-
170
- raise error
171
-
172
- else
173
- @pool_mutex.synchronize { @pool << session }
174
- end
175
-
176
- response
177
-
178
- end
179
-
180
144
  # Returns the number of sessions currently in the pool, not counting those
181
145
  # currently in use.
182
146
  def size
183
- @pool_mutex.synchronize { @pool.size }
147
+ @pool_mutex.synchronize { @pool.size }
184
148
  end
185
149
 
186
- # Removes stale http sessions from the pool (that have exceeded
150
+ # Removes stale http sessions from the pool (that have exceeded
187
151
  # the idle timeout).
188
152
  def clean!
189
153
  @pool_mutex.synchronize { _clean }
190
154
  end
191
155
 
192
- # Closes and removes removes all sessions from the pool.
156
+ # Closes and removes removes all sessions from the pool.
193
157
  # If empty! is called while there are outstanding requests they may
194
158
  # get checked back into the pool, leaving the pool in a non-empty state.
195
159
  def empty!
@@ -199,33 +163,57 @@ class Net::HTTP::ConnectionPool
199
163
  end
200
164
  end
201
165
 
202
- # Returns a suitable session from the pool or creates a new one
203
- private
204
- def session_for connection, force_new = false
166
+ # Makes a single HTTP request. See {Connection#request} for more information
167
+ # on making an HTTP request.
168
+ # @return [nil]
169
+ # @private
170
+ def request connection, *args, &block
171
+ session_for(connection) do |session|
172
+ session.read_timeout = connection.read_timeout
173
+ session.request(*args, &block)
174
+ end
175
+ end
176
+
177
+ protected
178
+
179
+ # Yields an open http session for the given connection.
180
+ def session_for connection, &block
205
181
 
206
182
  session = nil
207
183
 
208
- unless force_new
209
- @pool_mutex.synchronize do
210
- _clean
211
- session = @pool.find{|idle_session| idle_session.key == connection.key }
212
- @pool.delete(session) if session
213
- end
184
+ # search the pool for an idle session that can be used
185
+ @pool_mutex.synchronize do
186
+ _clean # removes stale sessions
187
+ session = @pool.find{|idle_session| idle_session.key == connection.key }
188
+ @pool.delete(session) if session
214
189
  end
215
190
 
216
- if session.nil?
217
- logger = http_wire_trace? ? self.logger : nil
218
- session = Session.for(connection, open_timeout, logger)
191
+ begin
192
+ # opens a new HTTP session if no suitable idle session was found
193
+ session = _create_session(connection) unless session
194
+ yield(session)
195
+ rescue Exception => error
196
+ session.finish if session
197
+ raise error
198
+ else
199
+ # only check the session back into the pool if no errors were raised
200
+ @pool_mutex.synchronize { @pool << session }
219
201
  end
220
202
 
221
- session
203
+ nil
204
+
205
+ end
206
+
207
+ def _create_session connection
208
+ Session.start(connection,
209
+ :open_timeout => open_timeout,
210
+ :debug_logger => log_wire_trace? ? logger : nil)
222
211
  end
223
212
 
224
- private
225
213
  def _clean
226
214
  now = Time.now
227
215
  @pool.delete_if do |idle_session|
228
- if
216
+ if
229
217
  idle_session.last_used_at.nil? or
230
218
  now - idle_session.last_used_at > idle_timeout
231
219
  then
@@ -15,17 +15,34 @@ require 'uri'
15
15
 
16
16
  class Net::HTTP::ConnectionPool
17
17
 
18
- # A light wrapper around Net::HTTP.
18
+ # Represents a HTTP connection. Call {#request} on a connection like
19
+ # you would with a Net::HTTPSession object.
19
20
  #
20
- # You should not need to construct connection objects yourself.
21
- # You receive them as a response to {ConnectionPool#connection_for}.
21
+ # == Getting a Connection object
22
+ #
23
+ # To get a connection object, you start with a connection pool:
24
+ #
25
+ # pool = Net::HTTP::ConnectionPool.new
26
+ # connection = pool.connection_for('domain.com')
27
+ #
28
+ # {ConnectionPool#connection_for} accepts a number of options to control
29
+ # the connection settings (SSL, proxy, timeouts, etc).
30
+ #
31
+ # == Making Requests
32
+ #
33
+ # Given a connection object, you call #request. {Connection#request}
34
+ # yields Net::HTTPResponse objects (when given a block). You should
35
+ # read the response (via #body or #read_body) before the end of the
36
+ # block.
37
+ #
38
+ # connection.request(Net::HTTP::Get.new('/')) do |resp|
39
+ # puts resp.body
40
+ # end
22
41
  #
23
42
  class Connection
24
43
 
25
- # @param [ConnectionPool] pool
26
- # @param (see ConnectionPool#connection_for)
27
- # @option (see ConnectionPool#connection_for)
28
- # @return [Connection]
44
+ # Use {ConnectionPool#connection_for} to construct {Connection} objects.
45
+ # @private
29
46
  def initialize pool, host, options = {}
30
47
 
31
48
  @pool = pool
@@ -96,35 +113,72 @@ class Net::HTTP::ConnectionPool
96
113
  # @return [Numeric,nil]
97
114
  attr_accessor :read_timeout
98
115
 
99
- # @return [Boolean] Returns true if this connection requires SSL.
116
+ # @return [Boolean] Returns +true+ if this connection requires SSL.
100
117
  def ssl?
101
118
  @ssl
102
119
  end
103
120
 
104
- # @return [Boolean] Returns true if ssl connections should verify the
121
+ # @return [Boolean] Returns +true+ if ssl connections should verify the
105
122
  # peer certificate.
106
123
  def ssl_verify_peer?
107
124
  @ssl_verify_peer
108
125
  end
109
126
 
110
- # @return [Boolean] Returns true if this connection proxies requests.
127
+ # @return [Boolean] Returns +true+ if this connection proxies requests.
111
128
  def proxy?
112
129
  !!proxy_address
113
130
  end
114
131
 
115
- # Makes a HTTP request. See Net::HTTPSession#request documentation
116
- # from the Ruby standard library for information about argments.
117
- # @return [Net::HTTPResponse]
132
+ # Makes a single HTTP request. The Net::HTTPResponse is yielded to the
133
+ # given block.
134
+ #
135
+ # pool = Net::HTTP::ConnectionPool.new
136
+ # connection = pool.connection_for('www.google.com')
137
+ #
138
+ # connection.request(Net::HTTP::Get.new('/')) do |response|
139
+ # # yeilds a Net::HTTPResponse object
140
+ # puts "STATUS CODE: #{response.code}"
141
+ # puts "HEADERS: #{response.to_hash.inspect}"
142
+ # puts "BODY:\n#{response.body}"
143
+ # end
144
+ #
145
+ # If you want to read the HTTP response body in chunks (useful for
146
+ # large responses you do not want to load into memory), you should
147
+ # pass a block to the #read_body method of the yielded response.
148
+ #
149
+ # File.open('output.txt', 'w') do |file|
150
+ # connection.request(Net::HTTP::Get.new('/')) do |response|
151
+ # response.read_body do |chunk|
152
+ # file.write(chunk)
153
+ # end
154
+ # end
155
+ # end
156
+ #
157
+ # If you omit the block when calling #request, you will not be able
158
+ # to read the response. This method never returns the
159
+ # Net::HTTPResponse generated.
160
+ #
161
+ # This method passes *args to Net::HTTPSession#request. See the
162
+ # Ruby standard lib documentation for more documentation about
163
+ # accepted arguments.
164
+ #
165
+ # @note You should read the yielded response object before the end
166
+ # of the passed block. Do no save a reference to yielded response
167
+ # objects.
168
+ #
169
+ # @yield [response]
170
+ # @yieldparam [Net::HTTPResponse] response
171
+ # @return [nil]
118
172
  def request *args, &block
119
173
  pool.request(self, *args, &block)
120
174
  end
121
175
 
122
176
  # @return [String] Returns a key that can be used to group connections
123
- # that connection to the same host.
177
+ # that may share the same HTTP sessions.
124
178
  def key
125
179
  @key ||= begin
126
180
  %w(
127
- host port
181
+ host port
128
182
  ssl ssl_verify_peer ssl_ca_file ssl_ca_path
129
183
  proxy_address proxy_port proxy_user proxy_password
130
184
  ).map{|part| send(part).to_s }.join(":")
@@ -17,9 +17,13 @@ require 'openssl'
17
17
 
18
18
  class Net::HTTP::ConnectionPool
19
19
 
20
+ # Used by Net::HTTP::ConnectionPool to wrap Net::HTTP::Session objects.
21
+ # Users should never need to interact with these session wrappers.
20
22
  # @private
21
23
  class Session
22
24
 
25
+ # @param [Net::HTTPSession] http_session
26
+ # @param [String] key
23
27
  def initialize http_session, key
24
28
  @http_session = http_session
25
29
  @key = key
@@ -27,20 +31,42 @@ class Net::HTTP::ConnectionPool
27
31
  @last_used_at = nil
28
32
  end
29
33
 
34
+ # @return [Net::HTTPSession]
30
35
  attr_reader :http_session
31
36
 
37
+ # @return [String]
32
38
  attr_reader :key
33
39
 
40
+ # @return [Time]
34
41
  attr_reader :created_at
35
42
 
43
+ # @return [Time]
36
44
  attr_reader :last_used_at
37
45
 
46
+ # @param [Integer] timeout Number of seconds before Net::HTTP should
47
+ # timeout while waiting to read a response.
48
+ def read_timeout= timeout
49
+ http_session.read_timeout = timeout
50
+ end
51
+
52
+ # Makes a HTTP request. See Net::HTTPSession#request documentation
53
+ # from the Ruby standard library for information about argments.
54
+ #
55
+ # connection.request(Net::HTTP::Get.new('/')) do |response|
56
+ # # Parse the response (status, headers and body) here.
57
+ # # You should be done with the response by the end of the block.
58
+ # end
59
+ #
60
+ # @yield [response]
61
+ # @yieldparam [Net::HTTPResponse] response
62
+ # @return [nil]
38
63
  def request *args, &block
39
- response = http_session.request(*args, &block)
64
+ http_session.request(*args, &block)
40
65
  @last_used_at = Time.now
41
- response
66
+ nil
42
67
  end
43
68
 
69
+ # Attempts to cleanly close the HTTP session.
44
70
  # @return [nil]
45
71
  def finish
46
72
  begin
@@ -52,7 +78,15 @@ class Net::HTTP::ConnectionPool
52
78
 
53
79
  class << self
54
80
 
55
- def for connection, open_timeout, debug_logger = nil
81
+ # Starts a new HTTP session and returns it wrapped in a {Session} object.
82
+ # @param [Connection] connection
83
+ # @param [Hash] options
84
+ # @option options [Integer] :open_timeout (15) The number of seconds to
85
+ # wait while trying to open the HTTP session before timeing out.
86
+ # @option options [Logger] :debug_logger HTTP wire traces are logged
87
+ # here when specified.
88
+ # @return [Session]
89
+ def start connection, options = {}
56
90
 
57
91
  http_args = []
58
92
  http_args << connection.host
@@ -65,8 +99,8 @@ class Net::HTTP::ConnectionPool
65
99
  end
66
100
 
67
101
  http = Net::HTTP.new(*http_args)
68
- http.set_debug_output(debug_logger)
69
- http.open_timeout = open_timeout
102
+ http.set_debug_output(options[:debug_logger]) if options[:debug_logger]
103
+ http.open_timeout = options[:open_timeout] || 15
70
104
 
71
105
  if connection.ssl?
72
106
  http.use_ssl = true
@@ -88,6 +122,5 @@ class Net::HTTP::ConnectionPool
88
122
  end
89
123
 
90
124
  end
91
-
92
125
  end
93
126
  end