From c320809d2b9635c0dc83cd4eda0c4e9f4a95cfba Mon Sep 17 00:00:00 2001 From: Untoldwind Date: Fri, 14 Jan 2011 21:31:19 +0100 Subject: [PATCH 1/3] Quick and Dirty fix for EU Buckets --- lib/aws/s3/authentication.rb | 13 ++++++++++--- lib/aws/s3/base.rb | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/aws/s3/authentication.rb b/lib/aws/s3/authentication.rb index 0efbc7a..dab4a1a 100644 --- a/lib/aws/s3/authentication.rb +++ b/lib/aws/s3/authentication.rb @@ -156,7 +156,8 @@ def initialize(request, options = {}) # "For non-authenticated or anonymous requests. A NotImplemented error result code will be returned if # an authenticated (signed) request specifies a Host: header other than 's3.amazonaws.com'" # (from http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html) - request['Host'] = DEFAULT_HOST + # ... and now CanonicalString will be fix if request['Host'] is set + # request['Host'] = DEFAULT_HOST build end @@ -213,9 +214,15 @@ def extract_significant_parameter end def only_path - request.path[/^[^?]*/] + # Check if a VirtualHost "bucket.s3.amazonaws.com" is set + # If the the path in the canonical string has to be "/bucket/request_path" + if ( request['Host'] =~ /^(.+)\.s3\.amazonaws\.com$/ ) + '/' + $1 + request.path[/^[^?]*/] + else + request.path[/^[^?]*/] + end end end end end -end \ No newline at end of file +end diff --git a/lib/aws/s3/base.rb b/lib/aws/s3/base.rb index 63abafa..35f4b6c 100644 --- a/lib/aws/s3/base.rb +++ b/lib/aws/s3/base.rb @@ -66,6 +66,23 @@ class << self def request(verb, path, options = {}, body = nil, attempts = 0, &block) Service.response = nil process_options!(options, verb) + + # Quick and dirty fix to access buckets the VirtualHost-way + # / => goes to "s3.amazonaws.com" / + # /bucket => goes to "bucket.s3.amazonaws.com" / + # /bucket/key => goest to "bucket.s3.amazonaws.com" /key + case path + when /^\/(\?.*)?$/ then + path = '/' + ($1 || '') + options['Host'] = DEFAULT_HOST + when /^\/([^\?\/]+)(\?.*)?$/ then + path = '/' + ($2 || '') + options['Host'] = $1 + '.' + DEFAULT_HOST + when /^\/([^\?\/]+)([^\?]+)(\?.*)?$/ then + path = $2 + ($3 || '') + options['Host'] = host = $1 + '.' + DEFAULT_HOST + end + response = response_class.new(connection.request(verb, path, options, body, attempts, &block)) Service.response = response From f6589af9b30fe8f0cc1cba604762dcaadaf3c7b9 Mon Sep 17 00:00:00 2001 From: Untoldwind Date: Fri, 14 Jan 2011 21:55:17 +0100 Subject: [PATCH 2/3] Fixed url_for as well --- lib/aws/s3/base.rb | 17 ----------------- lib/aws/s3/connection.rb | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/aws/s3/base.rb b/lib/aws/s3/base.rb index 35f4b6c..63abafa 100644 --- a/lib/aws/s3/base.rb +++ b/lib/aws/s3/base.rb @@ -66,23 +66,6 @@ class << self def request(verb, path, options = {}, body = nil, attempts = 0, &block) Service.response = nil process_options!(options, verb) - - # Quick and dirty fix to access buckets the VirtualHost-way - # / => goes to "s3.amazonaws.com" / - # /bucket => goes to "bucket.s3.amazonaws.com" / - # /bucket/key => goest to "bucket.s3.amazonaws.com" /key - case path - when /^\/(\?.*)?$/ then - path = '/' + ($1 || '') - options['Host'] = DEFAULT_HOST - when /^\/([^\?\/]+)(\?.*)?$/ then - path = '/' + ($2 || '') - options['Host'] = $1 + '.' + DEFAULT_HOST - when /^\/([^\?\/]+)([^\?]+)(\?.*)?$/ then - path = $2 + ($3 || '') - options['Host'] = host = $1 + '.' + DEFAULT_HOST - end - response = response_class.new(connection.request(verb, path, options, body, attempts, &block)) Service.response = response diff --git a/lib/aws/s3/connection.rb b/lib/aws/s3/connection.rb index 1b91127..f4cd2ac 100644 --- a/lib/aws/s3/connection.rb +++ b/lib/aws/s3/connection.rb @@ -26,6 +26,8 @@ def initialize(options = {}) def request(verb, path, headers = {}, body = nil, attempts = 0, &block) body.rewind if body.respond_to?(:rewind) unless attempts.zero? + path = virtual_host_fix(path, headers) + 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) @@ -61,13 +63,35 @@ def url_for(path, options = {}) # Default to true unless explicitly false authenticate = true if authenticate.nil? path = self.class.prepare_path(path) - request = request_method(:get).new(path, {}) + + headers = {} + path = virtual_host_fix(path, headers) + + request = request_method(:get).new(path, headers) query_string = query_string_authentication(request, options) returning "#{protocol(options)}#{http.address}#{port_string}#{path}" do |url| url << "?#{query_string}" if authenticate end end + def virtual_host_fix(path, headers) + # Quick and dirty fix to access buckets the VirtualHost-way + # / => goes to "s3.amazonaws.com" / + # /bucket => goes to "bucket.s3.amazonaws.com" / + # /bucket/key => goest to "bucket.s3.amazonaws.com" /key + case path + when /^\/(\?.*)?$/ then + headers['Host'] = DEFAULT_HOST + return '/' + ($1 || '') + when /^\/([^\?\/]+)(\?.*)?$/ then + headers['Host'] = $1 + '.' + DEFAULT_HOST + return '/' + ($2 || '') + when /^\/([^\?\/]+)([^\?]+)(\?.*)?$/ then + headers['Host'] = host = $1 + '.' + DEFAULT_HOST + return $2 + ($3 || '') + end + end + def subdomain http.address[/^([^.]+).#{DEFAULT_HOST}$/, 1] end From 59e3cb29d3a961b9db75191d7f287cac4b18a0e8 Mon Sep 17 00:00:00 2001 From: Untoldwind Date: Fri, 14 Jan 2011 22:14:11 +0100 Subject: [PATCH 3/3] Even more compact solution --- lib/aws/s3/connection.rb | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/aws/s3/connection.rb b/lib/aws/s3/connection.rb index f4cd2ac..73c076c 100644 --- a/lib/aws/s3/connection.rb +++ b/lib/aws/s3/connection.rb @@ -26,7 +26,7 @@ def initialize(options = {}) def request(verb, path, headers = {}, body = nil, attempts = 0, &block) body.rewind if body.respond_to?(:rewind) unless attempts.zero? - path = virtual_host_fix(path, headers) + path, headers['Host'] = virtual_host_fix(path) requester = Proc.new do path = self.class.prepare_path(path) if attempts.zero? # Only escape the path once @@ -64,31 +64,27 @@ def url_for(path, options = {}) authenticate = true if authenticate.nil? path = self.class.prepare_path(path) - headers = {} - path = virtual_host_fix(path, headers) + path, virtual_host = virtual_host_fix(path) - request = request_method(:get).new(path, headers) + request = request_method(:get).new(path, { 'Host' => virtual_host }) query_string = query_string_authentication(request, options) returning "#{protocol(options)}#{http.address}#{port_string}#{path}" do |url| url << "?#{query_string}" if authenticate end end - def virtual_host_fix(path, headers) + def virtual_host_fix(path) # Quick and dirty fix to access buckets the VirtualHost-way # / => goes to "s3.amazonaws.com" / # /bucket => goes to "bucket.s3.amazonaws.com" / # /bucket/key => goest to "bucket.s3.amazonaws.com" /key case path - when /^\/(\?.*)?$/ then - headers['Host'] = DEFAULT_HOST - return '/' + ($1 || '') - when /^\/([^\?\/]+)(\?.*)?$/ then - headers['Host'] = $1 + '.' + DEFAULT_HOST - return '/' + ($2 || '') - when /^\/([^\?\/]+)([^\?]+)(\?.*)?$/ then - headers['Host'] = host = $1 + '.' + DEFAULT_HOST - return $2 + ($3 || '') + when /^(\/(\?.*)?)$/ then + return $1, DEFAULT_HOST + when /^\/([^\?\/]+)((\?.*)?)$/ then + return '/' + $2, $1 + '.' + DEFAULT_HOST + when /^\/([^\?\/]+)(([^\?]+)(\?.*)?)$/ then + return $2, $1 + '.' + DEFAULT_HOST end end