diff --git a/lib/aws/s3/base.rb b/lib/aws/s3/base.rb index 63abafa..8531140 100644 --- a/lib/aws/s3/base.rb +++ b/lib/aws/s3/base.rb @@ -43,6 +43,13 @@ module AWS #:nodoc: module S3 constant :DEFAULT_HOST, 's3.amazonaws.com' + # See: http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RequestEndpoints.html + ENDPOINTS = { + :us => 's3-us-west-1.amazonaws.com', + :asia => 's3-ap-southeast-1.amazonaws.com', + :europe => 's3-eu-west-1.amazonaws.com' + } + # AWS::S3::Base is the abstract super class of all classes who make requests against S3, such as the built in # Service, Bucket and S3Object classes. It provides methods for making requests, inferring or setting response classes, # processing request options, and accessing attributes from S3's response data. diff --git a/lib/aws/s3/connection.rb b/lib/aws/s3/connection.rb index 85dee2d..b4528e4 100644 --- a/lib/aws/s3/connection.rb +++ b/lib/aws/s3/connection.rb @@ -183,6 +183,9 @@ module ClassMethods # # * :server - The server to make requests to. You can use this to specify your bucket in the subdomain, # or your own domain's cname if you are using virtual hosted buckets. Defaults to s3.amazonaws.com. + # * :region - The region from which to take the default server. You can use this to ovverride the default + # server if you used a regional bucket from :europe, :asia or :us. This can't be used + # together with the :server setting. Defaults to nil. # * :port - The port to the requests should be made on. Defaults to 80 or 443 if the :use_ssl # argument is set. # * :use_ssl - Whether requests should be made over SSL. If set to true, the :port argument @@ -251,12 +254,12 @@ def default_connection 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, :region, :port, :use_ssl, :persistent, :proxy].freeze def initialize(options = {}) super() validate(options) - replace(:server => DEFAULT_HOST, :port => (options[:use_ssl] ? 443 : 80)) + replace(:server => options[:region] ? ENDPOINTS[options[:region]] : DEFAULT_HOST, :port => (options[:use_ssl] ? 443 : 80)) merge!(options) end @@ -273,6 +276,8 @@ def validate(options) invalid_options = options.keys - VALID_OPTIONS raise InvalidConnectionOption.new(invalid_options) unless invalid_options.empty? raise ArgumentError, "Missing proxy settings. Must specify at least :host." if options[:proxy] && !options[:proxy][:host] + raise ArgumentError, "Ambiguous server/region option: please don't use :server and :region options together." if options[:server] && options[:region] + raise ArgumentError, "Bad region: please use one of #{ENDPOINTS.keys.map(&:inspect).join(', ')}." if options[:region] && !ENDPOINTS.key?(options[:region]) end end end diff --git a/test/connection_test.rb b/test/connection_test.rb index 52919d0..e0fc971 100644 --- a/test/connection_test.rb +++ b/test/connection_test.rb @@ -212,6 +212,23 @@ def test_recognizing_that_the_settings_want_to_connect_through_a_proxy assert options.connecting_through_proxy? end + def test_server_and_region_settings_cant_live_together + assert_raises(ArgumentError) do + generate_options(:region => :europe, :server => "example.org") + end + end + + def test_server_setting_is_extracted_from_region + options = generate_options(:region => :europe) + assert_equal ENDPOINTS[:europe], options[:server] + end + + def test_region_is_a_valid_s3_endpoint + assert_raises(ArgumentError) do + generate_options(:region => :antartica) + end + end + private def assert_key_transfered(key, value, options) assert_equal value, options[key]