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/connection.rb b/lib/aws/s3/connection.rb index 1b91127..73c076c 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, headers['Host'] = virtual_host_fix(path) + 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,31 @@ 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, {}) + + path, virtual_host = virtual_host_fix(path) + + 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) + # 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 + return $1, DEFAULT_HOST + when /^\/([^\?\/]+)((\?.*)?)$/ then + return '/' + $2, $1 + '.' + DEFAULT_HOST + when /^\/([^\?\/]+)(([^\?]+)(\?.*)?)$/ then + return $2, $1 + '.' + DEFAULT_HOST + end + end + def subdomain http.address[/^([^.]+).#{DEFAULT_HOST}$/, 1] end