diff --git a/lib/aws/s3/connection.rb b/lib/aws/s3/connection.rb
index 1b91127..7d860c5 100644
--- a/lib/aws/s3/connection.rb
+++ b/lib/aws/s3/connection.rb
@@ -1,50 +1,51 @@
module AWS
module S3
class Connection #:nodoc:
+ @@conn_name = nil
class << self
def connect(options = {})
new(options)
end
-
+
def prepare_path(path)
path = path.remove_extended unless path.valid_utf8?
URI.escape(path)
end
end
-
+
attr_reader :access_key_id, :secret_access_key, :http, :options
-
- # Creates a new connection. Connections make the actual requests to S3, though these requests are usually
+
+ # Creates a new connection. Connections make the actual requests to S3, though these requests are usually
# called from subclasses of Base.
- #
+ #
# For details on establishing connections, check the Connection::Management::ClassMethods.
def initialize(options = {})
@options = Options.new(options)
connect
end
-
+
def request(verb, path, headers = {}, body = nil, attempts = 0, &block)
- body.rewind if body.respond_to?(:rewind) unless attempts.zero?
-
- requester = Proc.new do
+ body.rewind if body.respond_to?(:rewind) unless attempts.zero?
+
+ requester = Proc.new do
path = self.class.prepare_path(path) if attempts.zero? # Only escape the path once
request = request_method(verb).new(path, headers)
ensure_content_type!(request)
add_user_agent!(request)
authenticate!(request)
if body
- if body.respond_to?(:read)
- request.body_stream = body
- else
- request.body = body
+ if body.respond_to?(:read)
+ request.body_stream = body
+ else
+ request.body = body
end
- request.content_length = body.respond_to?(:lstat) ? body.stat.size : body.size
+ request.content_length = body.respond_to?(:lstat) ? body.stat.size : body.size
else
- request.content_length = 0
+ request.content_length = 0
end
http.request(request, &block)
end
-
+
if persistent?
http.start unless http.started?
requester.call
@@ -55,11 +56,11 @@ def request(verb, path, headers = {}, body = nil, attempts = 0, &block)
@http = create_connection
attempts == 3 ? raise : (attempts += 1; retry)
end
-
+
def url_for(path, options = {})
authenticate = options.delete(:authenticated)
# Default to true unless explicitly false
- authenticate = true if authenticate.nil?
+ authenticate = true if authenticate.nil?
path = self.class.prepare_path(path)
request = request_method(:get).new(path, {})
query_string = query_string_authentication(request, options)
@@ -67,18 +68,18 @@ def url_for(path, options = {})
url << "?#{query_string}" if authenticate
end
end
-
+
def subdomain
http.address[/^([^.]+).#{DEFAULT_HOST}$/, 1]
end
-
+
def persistent?
options[:persistent]
end
-
+
def protocol(options = {})
# This always trumps http.use_ssl?
- if options[:use_ssl] == false
+ if options[:use_ssl] == false
'http://'
elsif options[:use_ssl] || http.use_ssl?
'https://'
@@ -86,7 +87,7 @@ def protocol(options = {})
'http://'
end
end
-
+
private
def extract_keys!
missing_keys = []
@@ -95,14 +96,14 @@ def extract_keys!
@secret_access_key = extract_key[:secret_access_key]
raise MissingAccessKey.new(missing_keys) unless missing_keys.empty?
end
-
+
def create_connection
http = http_class.new(options[:server], options[:port])
http.use_ssl = !options[:use_ssl].nil? || options[:port] == 443
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http
end
-
+
def http_class
if options.connecting_through_proxy?
Net::HTTP::Proxy(*options.proxy_settings)
@@ -110,7 +111,7 @@ def http_class
Net::HTTP
end
end
-
+
def connect
extract_keys!
@http = create_connection
@@ -124,16 +125,16 @@ def port_string
def ensure_content_type!(request)
request['Content-Type'] ||= 'binary/octet-stream'
end
-
+
# Just do Header authentication for now
def authenticate!(request)
request['Authorization'] = Authentication::Header.new(request, access_key_id, secret_access_key)
end
-
+
def add_user_agent!(request)
request['User-Agent'] ||= "AWS::S3/#{Version}"
end
-
+
def query_string_authentication(request, options = {})
Authentication::QueryString.new(request, access_key_id, secret_access_key, options)
end
@@ -141,29 +142,29 @@ def query_string_authentication(request, options = {})
def request_method(verb)
Net::HTTP.const_get(verb.to_s.capitalize)
end
-
+
def method_missing(method, *args, &block)
options[method] || super
end
-
+
module Management #:nodoc:
def self.included(base)
base.cattr_accessor :connections
base.connections = {}
base.extend ClassMethods
end
-
+
# Manage the creation and destruction of connections for AWS::S3::Base and its subclasses. Connections are
# created with establish_connection!.
module ClassMethods
# Creates a new connection with which to make requests to the S3 servers for the calling class.
- #
+ #
# AWS::S3::Base.establish_connection!(:access_key_id => '...', :secret_access_key => '...')
#
# You can set connections for every subclass of AWS::S3::Base. Once the initial connection is made on
# Base, all subsequent connections will inherit whatever values you don't specify explictly. This allows you to
- # customize details of the connection, such as what server the requests are made to, by just specifying one
- # option.
+ # customize details of the connection, such as what server the requests are made to, by just specifying one
+ # option.
#
# AWS::S3::Bucket.established_connection!(:use_ssl => true)
#
@@ -185,23 +186,23 @@ module ClassMethods
# argument is set.
# * :use_ssl - Whether requests should be made over SSL. If set to true, the :port argument
# will be implicitly set to 443, unless specified otherwise. Defaults to false.
- # * :persistent - Whether to use a persistent connection to the server. Having this on provides around a two fold
+ # * :persistent - Whether to use a persistent connection to the server. Having this on provides around a two fold
# performance increase but for long running processes some firewalls may find the long lived connection suspicious and close the connection.
# If you run into connection errors, try setting :persistent to false. Defaults to false.
# * :proxy - If you need to connect through a proxy, you can specify your proxy settings by specifying a :host, :port, :user, and :password
# with the :proxy option.
- # The :host setting is required if specifying a :proxy.
- #
+ # The :host setting is required if specifying a :proxy.
+ #
# AWS::S3::Bucket.established_connection!(:proxy => {
# :host => '...', :port => 8080, :user => 'marcel', :password => 'secret'
# })
def establish_connection!(options = {})
- # After you've already established the default connection, just specify
+ # After you've already established the default connection, just specify
# the difference for subsequent connections
- options = default_connection.options.merge(options) if connected?
+ @@conn_name = options[:connection_name] ? options[:connection_name] : nil
connections[connection_name] = Connection.connect(options)
end
-
+
# Returns the connection for the current class, or Base's default connection if the current class does not
# have its own connection.
#
@@ -213,29 +214,29 @@ def connection
raise NoConnectionEstablished
end
end
-
+
# Returns true if a connection has been made yet.
def connected?
!connections.empty?
end
-
+
# Removes the connection for the current class. If there is no connection for the current class, the default
# connection will be removed.
def disconnect(name = connection_name)
- name = default_connection unless connections.has_key?(name)
+ name = default_connection unless connections.has_key?(@@conn_name)
connection = connections[name]
connection.http.finish if connection.persistent?
connections.delete(name)
end
-
- # Clears *all* connections, from all classes, with prejudice.
+
+ # Clears *all* connections, from all classes, with prejudice.
def disconnect!
connections.each_key {|connection| disconnect(connection)}
end
private
def connection_name
- name
+ @@conn_name || name
end
def default_connection_name
@@ -247,10 +248,10 @@ def default_connection
end
end
end
-
+
class Options < Hash #:nodoc:
- VALID_OPTIONS = [:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy].freeze
-
+ VALID_OPTIONS = [:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy, :connection_name].freeze
+
def initialize(options = {})
super()
validate(options)
@@ -261,11 +262,11 @@ def initialize(options = {})
def connecting_through_proxy?
!self[:proxy].nil?
end
-
+
def proxy_settings
self[:proxy].values_at(:host, :port, :user, :password)
end
-
+
private
def validate(options)
invalid_options = options.keys - VALID_OPTIONS
@@ -275,4 +276,5 @@ def validate(options)
end
end
end
-end
\ No newline at end of file
+end
+