mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
AWS | storage: big refactor
Logics have been centralised: * region to hostname * url generation * signature * chaning scheme also changes the port During the process a couple of inconsistencies have also been fixed. Known limitations: When using the @endpoint with a custom port you need to specify the port when using get_object_http_url or get_object_https_url. When using bucket names that contain dots outside of us-east-1 make sure to access it with the same region in your AWS::Storage.
This commit is contained in:
parent
f36a3065a9
commit
f6d361b2e2
49 changed files with 274 additions and 210 deletions
|
@ -3,8 +3,6 @@ require 'fog/aws/credential_fetcher'
|
||||||
require 'fog/aws/signaturev4'
|
require 'fog/aws/signaturev4'
|
||||||
module Fog
|
module Fog
|
||||||
module AWS
|
module AWS
|
||||||
COMPLIANT_BUCKET_NAMES = /^(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}$))(?:[a-z0-9]|\-(?![\.])){1,61}[a-z0-9]$/
|
|
||||||
|
|
||||||
extend Fog::Provider
|
extend Fog::Provider
|
||||||
|
|
||||||
service(:auto_scaling, 'aws/auto_scaling', 'AutoScaling')
|
service(:auto_scaling, 'aws/auto_scaling', 'AutoScaling')
|
||||||
|
|
|
@ -80,11 +80,9 @@ module Fog
|
||||||
def public_url
|
def public_url
|
||||||
requires :key
|
requires :key
|
||||||
if service.get_bucket_acl(key).body['AccessControlList'].detect {|grant| grant['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AllUsers' && grant['Permission'] == 'READ'}
|
if service.get_bucket_acl(key).body['AccessControlList'].detect {|grant| grant['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AllUsers' && grant['Permission'] == 'READ'}
|
||||||
if key.to_s =~ Fog::AWS::COMPLIANT_BUCKET_NAMES
|
service.request_url(
|
||||||
"https://#{key}.s3.amazonaws.com"
|
:bucket_name => key
|
||||||
else
|
)
|
||||||
"https://s3.amazonaws.com/#{key}"
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -163,11 +163,10 @@ module Fog
|
||||||
def public_url
|
def public_url
|
||||||
requires :directory, :key
|
requires :directory, :key
|
||||||
if service.get_object_acl(directory.key, key).body['AccessControlList'].detect {|grant| grant['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AllUsers' && grant['Permission'] == 'READ'}
|
if service.get_object_acl(directory.key, key).body['AccessControlList'].detect {|grant| grant['Grantee']['URI'] == 'http://acs.amazonaws.com/groups/global/AllUsers' && grant['Permission'] == 'READ'}
|
||||||
if directory.key.to_s =~ Fog::AWS::COMPLIANT_BUCKET_NAMES
|
service.request_url(
|
||||||
"https://#{directory.key}.s3.amazonaws.com/#{Fog::AWS.escape(key)}".gsub('%2F','/')
|
:bucket_name => directory.key,
|
||||||
else
|
:object_name => key
|
||||||
"https://s3.amazonaws.com/#{directory.key}/#{Fog::AWS.escape(key)}".gsub('%2F','/')
|
)
|
||||||
end
|
|
||||||
else
|
else
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,9 +15,9 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:method => 'DELETE',
|
:method => 'DELETE',
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => {'uploadId' => upload_id}
|
:query => {'uploadId' => upload_id}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -25,4 +25,4 @@ module Fog
|
||||||
end # Real
|
end # Real
|
||||||
end # Storage
|
end # Storage
|
||||||
end # AWS
|
end # AWS
|
||||||
end # Fog
|
end # Fog
|
||||||
|
|
|
@ -34,10 +34,10 @@ module Fog
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => { 'Content-Length' => data.length },
|
:headers => { 'Content-Length' => data.length },
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:method => 'POST',
|
:method => 'POST',
|
||||||
:parser => Fog::Parsers::Storage::AWS::CompleteMultipartUpload.new,
|
:parser => Fog::Parsers::Storage::AWS::CompleteMultipartUpload.new,
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => {'uploadId' => upload_id}
|
:query => {'uploadId' => upload_id}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,10 +33,10 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{target_bucket_name}.#{@host}",
|
:bucket_name => target_bucket_name,
|
||||||
|
:object_name => target_object_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:parser => Fog::Parsers::Storage::AWS::CopyObject.new,
|
:parser => Fog::Parsers::Storage::AWS::CopyObject.new,
|
||||||
:path => CGI.escape(target_object_name)
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'DELETE'
|
:method => 'DELETE'
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'DELETE',
|
:method => 'DELETE',
|
||||||
:query => {'cors' => nil}
|
:query => {'cors' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,7 +16,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'DELETE',
|
:method => 'DELETE',
|
||||||
:query => {'lifecycle' => nil}
|
:query => {'lifecycle' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,7 +16,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'DELETE',
|
:method => 'DELETE',
|
||||||
:query => {'policy' => nil}
|
:query => {'policy' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,7 +16,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'DELETE',
|
:method => 'DELETE',
|
||||||
:query => {'website' => nil}
|
:query => {'website' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -55,7 +55,7 @@ module Fog
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'POST',
|
:method => 'POST',
|
||||||
:parser => Fog::Parsers::Storage::AWS::DeleteMultipleObjects.new,
|
:parser => Fog::Parsers::Storage::AWS::DeleteMultipleObjects.new,
|
||||||
:query => {'delete' => nil}
|
:query => {'delete' => nil}
|
||||||
|
|
|
@ -24,7 +24,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'DELETE',
|
:method => 'DELETE',
|
||||||
:path => path
|
:path => path
|
||||||
|
|
|
@ -44,7 +44,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetBucket.new,
|
:parser => Fog::Parsers::Storage::AWS::GetBucket.new,
|
||||||
|
|
|
@ -33,7 +33,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::AccessControlList.new,
|
:parser => Fog::Parsers::Storage::AWS::AccessControlList.new,
|
||||||
|
|
|
@ -29,7 +29,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::CorsConfiguration.new,
|
:parser => Fog::Parsers::Storage::AWS::CorsConfiguration.new,
|
||||||
|
|
|
@ -23,7 +23,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetBucketLifecycle.new,
|
:parser => Fog::Parsers::Storage::AWS::GetBucketLifecycle.new,
|
||||||
|
|
|
@ -19,7 +19,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetBucketLocation.new,
|
:parser => Fog::Parsers::Storage::AWS::GetBucketLocation.new,
|
||||||
|
|
|
@ -33,7 +33,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetBucketLogging.new,
|
:parser => Fog::Parsers::Storage::AWS::GetBucketLogging.new,
|
||||||
|
|
|
@ -55,7 +55,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetBucketObjectVersions.new,
|
:parser => Fog::Parsers::Storage::AWS::GetBucketObjectVersions.new,
|
||||||
|
|
|
@ -19,7 +19,7 @@ module Fog
|
||||||
response = request({
|
response = request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:query => {'policy' => nil}
|
:query => {'policy' => nil}
|
||||||
|
|
|
@ -23,7 +23,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetBucketVersioning.new,
|
:parser => Fog::Parsers::Storage::AWS::GetBucketVersioning.new,
|
||||||
|
|
|
@ -26,7 +26,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetBucketWebsite.new,
|
:parser => Fog::Parsers::Storage::AWS::GetBucketWebsite.new,
|
||||||
|
|
|
@ -55,10 +55,10 @@ module Fog
|
||||||
|
|
||||||
request(params.merge!({
|
request(params.merge!({
|
||||||
:expects => [ 200, 206 ],
|
:expects => [ 200, 206 ],
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:path => CGI.escape(object_name)
|
|
||||||
}))
|
}))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -43,11 +43,11 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::AccessControlList.new,
|
:parser => Fog::Parsers::Storage::AWS::AccessControlList.new,
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => query
|
:query => query
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,25 +5,7 @@ module Fog
|
||||||
module GetObjectHttpUrl
|
module GetObjectHttpUrl
|
||||||
|
|
||||||
def get_object_http_url(bucket_name, object_name, expires, options = {})
|
def get_object_http_url(bucket_name, object_name, expires, options = {})
|
||||||
unless bucket_name
|
get_object_url(bucket_name, object_name, expires, options.merge(:scheme => 'http'))
|
||||||
raise ArgumentError.new('bucket_name is required')
|
|
||||||
end
|
|
||||||
unless object_name
|
|
||||||
raise ArgumentError.new('object_name is required')
|
|
||||||
end
|
|
||||||
host, path = if bucket_name =~ /^(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}$))(?:[a-z0-9]|\.(?![\.\-])|\-(?![\.])){1,61}[a-z0-9]$/
|
|
||||||
["#{bucket_name}.#{@host}", object_name]
|
|
||||||
else
|
|
||||||
[@host, "#{bucket_name}/#{object_name}"]
|
|
||||||
end
|
|
||||||
http_url({
|
|
||||||
:headers => {},
|
|
||||||
:host => host,
|
|
||||||
:port => @port,
|
|
||||||
:method => 'GET',
|
|
||||||
:path => path,
|
|
||||||
:query => options[:query]
|
|
||||||
}, expires)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,10 +33,10 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => {'torrent' => nil}
|
:query => {'torrent' => nil}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,20 +11,11 @@ module Fog
|
||||||
unless object_name
|
unless object_name
|
||||||
raise ArgumentError.new('object_name is required')
|
raise ArgumentError.new('object_name is required')
|
||||||
end
|
end
|
||||||
host, path = if bucket_name =~ Fog::AWS::COMPLIANT_BUCKET_NAMES
|
signed_url(options.merge({
|
||||||
["#{bucket_name}.#{@host}", object_name]
|
:bucket_name => bucket_name,
|
||||||
else
|
:object_name => object_name,
|
||||||
[@host, "#{bucket_name}/#{object_name}"]
|
:method => 'GET'
|
||||||
end
|
}), expires)
|
||||||
scheme_host_path_query({
|
|
||||||
:scheme => options[:scheme],
|
|
||||||
:headers => {},
|
|
||||||
:host => host,
|
|
||||||
:port => @port,
|
|
||||||
:method => 'GET',
|
|
||||||
:path => path,
|
|
||||||
:query => options[:query]
|
|
||||||
}, expires)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::GetRequestPayment.new,
|
:parser => Fog::Parsers::Storage::AWS::GetRequestPayment.new,
|
||||||
|
|
|
@ -42,10 +42,10 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'HEAD',
|
:method => 'HEAD',
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => query
|
:query => query
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,10 +30,10 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => options,
|
:headers => options,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:method => 'POST',
|
:method => 'POST',
|
||||||
:parser => Fog::Parsers::Storage::AWS::InitiateMultipartUpload.new,
|
:parser => Fog::Parsers::Storage::AWS::InitiateMultipartUpload.new,
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => {'uploads' => nil}
|
:query => {'uploads' => nil}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,7 +41,7 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::ListMultipartUploads.new,
|
:parser => Fog::Parsers::Storage::AWS::ListMultipartUploads.new,
|
||||||
|
|
|
@ -40,11 +40,11 @@ module Fog
|
||||||
request({
|
request({
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:parser => Fog::Parsers::Storage::AWS::ListParts.new,
|
:parser => Fog::Parsers::Storage::AWS::ListParts.new,
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => options.merge!({'uploadId' => upload_id})
|
:query => options.merge!({'uploadId' => upload_id})
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,7 +31,7 @@ DATA
|
||||||
:body => data,
|
:body => data,
|
||||||
:headers => options,
|
:headers => options,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT'
|
:method => 'PUT'
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -46,7 +46,7 @@ module Fog
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'acl' => nil}
|
:query => {'acl' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,7 +31,7 @@ module Fog
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'cors' => nil}
|
:query => {'cors' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -66,7 +66,7 @@ module Fog
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {'Content-MD5' => Base64.encode64(Digest::MD5.digest(body)).chomp!,
|
:headers => {'Content-MD5' => Base64.encode64(Digest::MD5.digest(body)).chomp!,
|
||||||
'Content-Type' => 'application/xml'},
|
'Content-Type' => 'application/xml'},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'lifecycle' => nil}
|
:query => {'lifecycle' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -69,7 +69,7 @@ DATA
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'logging' => nil}
|
:query => {'logging' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,7 +15,7 @@ module Fog
|
||||||
:body => Fog::JSON.encode(policy),
|
:body => Fog::JSON.encode(policy),
|
||||||
:expects => 204,
|
:expects => 204,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'policy' => nil}
|
:query => {'policy' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,7 +22,7 @@ DATA
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'versioning' => nil}
|
:query => {'versioning' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -35,7 +35,7 @@ DATA
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'website' => nil}
|
:query => {'website' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,10 +33,10 @@ module Fog
|
||||||
:body => data[:body],
|
:body => data[:body],
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:path => CGI.escape(object_name)
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,9 @@ module Fog
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => query
|
:query => query
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,14 +10,12 @@ module Fog
|
||||||
unless object_name
|
unless object_name
|
||||||
raise ArgumentError.new('object_name is required')
|
raise ArgumentError.new('object_name is required')
|
||||||
end
|
end
|
||||||
scheme_host_path_query({
|
signed_url(options.merge({
|
||||||
:scheme => options[:scheme],
|
:bucket_name => bucket_name,
|
||||||
:headers => headers,
|
:object_name => object_name,
|
||||||
:host => @host,
|
|
||||||
:port => @port,
|
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:path => "#{bucket_name}/#{object_name}"
|
:headers => headers,
|
||||||
}, expires)
|
}), expires)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ DATA
|
||||||
:body => data,
|
:body => data,
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:headers => {},
|
:headers => {},
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:query => {'requestPayment' => nil}
|
:query => {'requestPayment' => nil}
|
||||||
})
|
})
|
||||||
|
|
|
@ -28,9 +28,9 @@ module Fog
|
||||||
:expects => 200,
|
:expects => 200,
|
||||||
:idempotent => true,
|
:idempotent => true,
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:bucket_name => bucket_name,
|
||||||
|
:object_name => object_name,
|
||||||
:method => 'PUT',
|
:method => 'PUT',
|
||||||
:path => CGI.escape(object_name),
|
|
||||||
:query => {'uploadId' => upload_id, 'partNumber' => part_number}
|
:query => {'uploadId' => upload_id, 'partNumber' => part_number}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,8 +6,42 @@ module Fog
|
||||||
class AWS < Fog::Service
|
class AWS < Fog::Service
|
||||||
extend Fog::AWS::CredentialFetcher::ServiceMethods
|
extend Fog::AWS::CredentialFetcher::ServiceMethods
|
||||||
|
|
||||||
|
COMPLIANT_BUCKET_NAMES = /^(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}$))(?:[a-z0-9]|\.(?![\.\-])|\-(?![\.])){1,61}[a-z0-9]$/
|
||||||
|
|
||||||
DEFAULT_REGION = 'us-east-1'
|
DEFAULT_REGION = 'us-east-1'
|
||||||
|
|
||||||
|
DEFAULT_SCHEME = 'https'
|
||||||
|
DEFAULT_SCHEME_PORT = {
|
||||||
|
'http' => 80,
|
||||||
|
'https' => 443
|
||||||
|
}
|
||||||
|
|
||||||
|
VALID_QUERY_KEYS = %w[
|
||||||
|
acl
|
||||||
|
cors
|
||||||
|
delete
|
||||||
|
lifecycle
|
||||||
|
location
|
||||||
|
logging
|
||||||
|
notification
|
||||||
|
partNumber
|
||||||
|
policy
|
||||||
|
requestPayment
|
||||||
|
response-cache-control
|
||||||
|
response-content-disposition
|
||||||
|
response-content-encoding
|
||||||
|
response-content-language
|
||||||
|
response-content-type
|
||||||
|
response-expires
|
||||||
|
torrent
|
||||||
|
uploadId
|
||||||
|
uploads
|
||||||
|
versionId
|
||||||
|
versioning
|
||||||
|
versions
|
||||||
|
website
|
||||||
|
]
|
||||||
|
|
||||||
requires :aws_access_key_id, :aws_secret_access_key
|
requires :aws_access_key_id, :aws_secret_access_key
|
||||||
recognizes :endpoint, :region, :host, :path, :port, :scheme, :persistent, :use_iam_profile, :aws_session_token, :aws_credentials_expire_at, :path_style
|
recognizes :endpoint, :region, :host, :path, :port, :scheme, :persistent, :use_iam_profile, :aws_session_token, :aws_credentials_expire_at, :path_style
|
||||||
|
|
||||||
|
@ -81,11 +115,11 @@ module Fog
|
||||||
end
|
end
|
||||||
|
|
||||||
def http_url(params, expires)
|
def http_url(params, expires)
|
||||||
scheme_host_path_query(params.merge(:scheme => 'http', :port => 80), expires)
|
signed_url(params.merge(:scheme => 'http'), expires)
|
||||||
end
|
end
|
||||||
|
|
||||||
def https_url(params, expires)
|
def https_url(params, expires)
|
||||||
scheme_host_path_query(params.merge(:scheme => 'https', :port => 443), expires)
|
signed_url(params.merge(:scheme => 'https'), expires)
|
||||||
end
|
end
|
||||||
|
|
||||||
def url(params, expires)
|
def url(params, expires)
|
||||||
|
@ -93,32 +127,120 @@ module Fog
|
||||||
https_url(params, expires)
|
https_url(params, expires)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def request_url(params)
|
||||||
|
params = request_params(params)
|
||||||
|
params_to_url(params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def signed_url(params, expires)
|
||||||
|
expires = expires.to_i
|
||||||
|
signature = signature(params, expires)
|
||||||
|
params = request_params(params)
|
||||||
|
|
||||||
|
params[:query] = (params[:query] || {}).merge({
|
||||||
|
'AWSAccessKeyId' => @aws_access_key_id,
|
||||||
|
'Signature' => signature,
|
||||||
|
'Expires' => expires,
|
||||||
|
})
|
||||||
|
params[:query]['x-amz-security-token'] = @aws_session_token if @aws_session_token
|
||||||
|
|
||||||
|
params_to_url(params)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def scheme_host_path_query(params, expires)
|
def region_to_host(region=nil)
|
||||||
params[:scheme] ||= @scheme
|
case region.to_s
|
||||||
if params[:port] == 80 && params[:scheme] == 'http'
|
when DEFAULT_REGION, ''
|
||||||
params.delete(:port)
|
's3.amazonaws.com'
|
||||||
|
else
|
||||||
|
"s3-#{region}.amazonaws.com"
|
||||||
end
|
end
|
||||||
if params[:port] == 443 && params[:scheme] == 'https'
|
end
|
||||||
params.delete(:port)
|
|
||||||
|
def object_to_path(object_name=nil)
|
||||||
|
'/' + Fog::AWS.escape(object_name.to_s).gsub('%2F','/')
|
||||||
|
end
|
||||||
|
|
||||||
|
# Transforms things like bucket_name, object_name, region
|
||||||
|
#
|
||||||
|
# Should yield the same result when called f*f
|
||||||
|
def request_params(params)
|
||||||
|
headers = params[:headers] || {}
|
||||||
|
|
||||||
|
if params[:scheme]
|
||||||
|
scheme = params[:scheme]
|
||||||
|
port = params[:port]
|
||||||
|
else
|
||||||
|
scheme = @scheme || DEFAULT_SCHEME
|
||||||
|
port = @port
|
||||||
end
|
end
|
||||||
params[:headers] ||= {}
|
if DEFAULT_SCHEME_PORT[scheme] == port
|
||||||
params[:headers]['Date'] = expires.to_i
|
port = nil
|
||||||
params[:path] = Fog::AWS.escape(params[:path]).gsub('%2F', '/')
|
end
|
||||||
query = []
|
|
||||||
params[:headers]['x-amz-security-token'] = @aws_session_token if @aws_session_token
|
if params[:region]
|
||||||
if params[:query]
|
region = params[:region]
|
||||||
for key, value in params[:query]
|
host = params[:host] || region_to_host(region)
|
||||||
query << "#{key}=#{Fog::AWS.escape(value)}"
|
else
|
||||||
|
region = @region || DEFAULT_REGION
|
||||||
|
host = params[:host] || @host || region_to_host(region)
|
||||||
|
end
|
||||||
|
|
||||||
|
path = params[:path] || object_to_path(params[:object_name])
|
||||||
|
path = '/' + path if path[0..0] != '/'
|
||||||
|
|
||||||
|
if params[:bucket_name]
|
||||||
|
bucket_name = params[:bucket_name]
|
||||||
|
|
||||||
|
path_style = params.fetch(:path_style, @path_style)
|
||||||
|
if !path_style && COMPLIANT_BUCKET_NAMES !~ bucket_name
|
||||||
|
Fog::Logger.warning("fog: the specified s3 bucket name(#{bucket_name}) is not a valid dns name, which will negatively impact performance. For details see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/BucketRestrictions.html")
|
||||||
|
path_style = true
|
||||||
|
elsif bucket_name.include?('.')
|
||||||
|
Fog::Logger.warning("fog: the specified s3 bucket name(#{bucket_name}) might fail with https.")
|
||||||
|
end
|
||||||
|
|
||||||
|
if path_style
|
||||||
|
path = "/#{bucket_name}#{path}"
|
||||||
|
else
|
||||||
|
host = [bucket_name, host].join('.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
query << "AWSAccessKeyId=#{@aws_access_key_id}"
|
|
||||||
query << "Signature=#{Fog::AWS.escape(signature(params))}"
|
ret = params.merge({
|
||||||
query << "Expires=#{params[:headers]['Date']}"
|
:scheme => scheme,
|
||||||
query << "x-amz-security-token=#{Fog::AWS.escape(@aws_session_token)}" if @aws_session_token
|
:host => host,
|
||||||
port_part = params[:port] && ":#{params[:port]}"
|
:port => port,
|
||||||
"#{params[:scheme]}://#{params[:host]}#{port_part}/#{params[:path]}?#{query.join('&')}"
|
:path => path,
|
||||||
|
:headers => headers,
|
||||||
|
})
|
||||||
|
|
||||||
|
#
|
||||||
|
ret.delete(:path_style)
|
||||||
|
ret.delete(:bucket_name)
|
||||||
|
ret.delete(:object_name)
|
||||||
|
ret.delete(:region)
|
||||||
|
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
|
||||||
|
def params_to_url(params)
|
||||||
|
query = params[:query] && params[:query].map do |key, value|
|
||||||
|
if value
|
||||||
|
[key, Fog::AWS.escape(value.to_s)].join('=')
|
||||||
|
else
|
||||||
|
key
|
||||||
|
end
|
||||||
|
end.join('&')
|
||||||
|
|
||||||
|
URI::Generic.build({
|
||||||
|
:scheme => params[:scheme],
|
||||||
|
:host => params[:host],
|
||||||
|
:port => params[:port],
|
||||||
|
:path => params[:path],
|
||||||
|
:query => query,
|
||||||
|
}).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -212,15 +334,9 @@ module Fog
|
||||||
require 'mime/types'
|
require 'mime/types'
|
||||||
@use_iam_profile = options[:use_iam_profile]
|
@use_iam_profile = options[:use_iam_profile]
|
||||||
setup_credentials(options)
|
setup_credentials(options)
|
||||||
options[:region] ||= 'us-east-1'
|
@region = options[:region] || DEFAULT_REGION
|
||||||
@host = options[:host] || case options[:region]
|
@host = options[:host] || region_to_host(@region)
|
||||||
when 'us-east-1'
|
@scheme = options[:scheme] || DEFAULT_SCHEME
|
||||||
's3.amazonaws.com'
|
|
||||||
else
|
|
||||||
"s3-#{options[:region]}.amazonaws.com"
|
|
||||||
end
|
|
||||||
@scheme = options[:scheme] || 'https'
|
|
||||||
@region = options[:region]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def data
|
def data
|
||||||
|
@ -231,7 +347,7 @@ module Fog
|
||||||
self.class.data[@region].delete(@aws_access_key_id)
|
self.class.data[@region].delete(@aws_access_key_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def signature(params)
|
def signature(params, expires)
|
||||||
"foo"
|
"foo"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -272,6 +388,7 @@ module Fog
|
||||||
@use_iam_profile = options[:use_iam_profile]
|
@use_iam_profile = options[:use_iam_profile]
|
||||||
setup_credentials(options)
|
setup_credentials(options)
|
||||||
@connection_options = options[:connection_options] || {}
|
@connection_options = options[:connection_options] || {}
|
||||||
|
@persistent = options.fetch(:persistent, false)
|
||||||
|
|
||||||
if @endpoint = options[:endpoint]
|
if @endpoint = options[:endpoint]
|
||||||
endpoint = URI.parse(@endpoint)
|
endpoint = URI.parse(@endpoint)
|
||||||
|
@ -281,23 +398,17 @@ module Fog
|
||||||
else
|
else
|
||||||
endpoint.path
|
endpoint.path
|
||||||
end
|
end
|
||||||
@port = endpoint.port
|
|
||||||
@scheme = endpoint.scheme
|
@scheme = endpoint.scheme
|
||||||
|
@port = endpoint.port
|
||||||
else
|
else
|
||||||
options[:region] ||= 'us-east-1'
|
@region = options[:region] || DEFAULT_REGION
|
||||||
@region = options[:region]
|
@host = options[:host] || region_to_host(@region)
|
||||||
@host = options[:host] || case options[:region]
|
|
||||||
when 'us-east-1'
|
|
||||||
's3.amazonaws.com'
|
|
||||||
else
|
|
||||||
"s3-#{options[:region]}.amazonaws.com"
|
|
||||||
end
|
|
||||||
@path = options[:path] || '/'
|
@path = options[:path] || '/'
|
||||||
@persistent = options.fetch(:persistent, false)
|
@scheme = options[:scheme] || DEFAULT_SCHEME
|
||||||
@port = options[:port] || 443
|
@port = options[:port] || DEFAULT_SCHEME_PORT[@scheme]
|
||||||
@scheme = options[:scheme] || 'https'
|
|
||||||
@path_style = options[:path_style] || false
|
@path_style = options[:path_style] || false
|
||||||
end
|
end
|
||||||
|
|
||||||
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}#{@path}", @persistent, @connection_options)
|
@connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}#{@path}", @persistent, @connection_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -305,17 +416,19 @@ module Fog
|
||||||
@connection.reset
|
@connection.reset
|
||||||
end
|
end
|
||||||
|
|
||||||
def signature(params)
|
def signature(params, expires)
|
||||||
|
headers = params[:headers] || {}
|
||||||
|
|
||||||
string_to_sign =
|
string_to_sign =
|
||||||
<<-DATA
|
<<-DATA
|
||||||
#{params[:method].to_s.upcase}
|
#{params[:method].to_s.upcase}
|
||||||
#{params[:headers]['Content-MD5']}
|
#{headers['Content-MD5']}
|
||||||
#{params[:headers]['Content-Type']}
|
#{headers['Content-Type']}
|
||||||
#{params[:headers]['Date']}
|
#{expires}
|
||||||
DATA
|
DATA
|
||||||
|
|
||||||
amz_headers, canonical_amz_headers = {}, ''
|
amz_headers, canonical_amz_headers = {}, ''
|
||||||
for key, value in params[:headers]
|
for key, value in headers
|
||||||
if key[0..5] == 'x-amz-'
|
if key[0..5] == 'x-amz-'
|
||||||
amz_headers[key] = value
|
amz_headers[key] = value
|
||||||
end
|
end
|
||||||
|
@ -326,57 +439,33 @@ DATA
|
||||||
end
|
end
|
||||||
string_to_sign << canonical_amz_headers
|
string_to_sign << canonical_amz_headers
|
||||||
|
|
||||||
subdomain = params[:host].split(".#{@host}").first
|
|
||||||
valid_dns = !!(subdomain =~ /^(?:[a-z]|\d(?!\d{0,2}(?:\.\d{1,3}){3}$))(?:[a-z0-9]|\.(?![\.\-])|\-(?![\.])){1,61}[a-z0-9]$/)
|
query_string = ''
|
||||||
if !valid_dns || @path_style
|
if params[:query]
|
||||||
Fog::Logger.warning("fog: the specified s3 bucket name(#{subdomain}) is not a valid dns name, which will negatively impact performance. For details see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/BucketRestrictions.html") unless valid_dns
|
query_args = []
|
||||||
params[:host] = params[:host].split("#{subdomain}.")[-1]
|
for key in params[:query].keys.sort
|
||||||
unless subdomain == @host
|
if VALID_QUERY_KEYS.include?(key)
|
||||||
if params[:path]
|
value = params[:query][key]
|
||||||
params[:path] = "#{subdomain}/#{params[:path]}"
|
if value
|
||||||
else
|
query_args << "#{key}=#{Fog::AWS.escape(value.to_s)}"
|
||||||
params[:path] = subdomain
|
else
|
||||||
|
query_args << key
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
subdomain = nil
|
if query_args.any?
|
||||||
end
|
query_string = '?' + query_args.join('&')
|
||||||
|
|
||||||
canonical_resource = @path.dup
|
|
||||||
unless subdomain.nil? || subdomain == @host
|
|
||||||
canonical_resource << "#{Fog::AWS.escape(subdomain).downcase}/"
|
|
||||||
end
|
|
||||||
canonical_resource << params[:path].to_s
|
|
||||||
canonical_resource << '?'
|
|
||||||
for key in (params[:query] || {}).keys.sort
|
|
||||||
if %w{
|
|
||||||
acl
|
|
||||||
cors
|
|
||||||
delete
|
|
||||||
lifecycle
|
|
||||||
location
|
|
||||||
logging
|
|
||||||
notification
|
|
||||||
partNumber
|
|
||||||
policy
|
|
||||||
requestPayment
|
|
||||||
response-cache-control
|
|
||||||
response-content-disposition
|
|
||||||
response-content-encoding
|
|
||||||
response-content-language
|
|
||||||
response-content-type
|
|
||||||
response-expires
|
|
||||||
torrent
|
|
||||||
uploadId
|
|
||||||
uploads
|
|
||||||
versionId
|
|
||||||
versioning
|
|
||||||
versions
|
|
||||||
website
|
|
||||||
}.include?(key)
|
|
||||||
canonical_resource << "#{key}#{"=#{params[:query][key]}" unless params[:query][key].nil?}&"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
canonical_resource.chop!
|
|
||||||
|
canonical_path = (params[:path] || object_to_path(params[:object_name])).to_s
|
||||||
|
canonical_path = '/' + canonical_path if canonical_path[0..0] != '/'
|
||||||
|
if params[:bucket_name]
|
||||||
|
canonical_resource = "/#{params[:bucket_name]}#{canonical_path}"
|
||||||
|
else
|
||||||
|
canonical_resource = canonical_path
|
||||||
|
end
|
||||||
|
canonical_resource << query_string
|
||||||
string_to_sign << canonical_resource
|
string_to_sign << canonical_resource
|
||||||
|
|
||||||
signed_string = @hmac.sign(string_to_sign)
|
signed_string = @hmac.sign(string_to_sign)
|
||||||
|
@ -397,16 +486,23 @@ DATA
|
||||||
def request(params, &block)
|
def request(params, &block)
|
||||||
refresh_credentials_if_expired
|
refresh_credentials_if_expired
|
||||||
|
|
||||||
params[:headers]['Date'] = Fog::Time.now.to_date_header
|
expires = Fog::Time.now.to_date_header
|
||||||
|
signature = signature(params, expires)
|
||||||
|
|
||||||
|
params = request_params(params)
|
||||||
|
params.delete(:port) unless params[:port]
|
||||||
|
|
||||||
|
params[:headers]['Date'] = expires
|
||||||
params[:headers]['x-amz-security-token'] = @aws_session_token if @aws_session_token
|
params[:headers]['x-amz-security-token'] = @aws_session_token if @aws_session_token
|
||||||
params[:headers]['Authorization'] = "AWS #{@aws_access_key_id}:#{signature(params)}"
|
params[:headers]['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
|
||||||
# FIXME: ToHashParser should make this not needed
|
# FIXME: ToHashParser should make this not needed
|
||||||
original_params = params.dup
|
original_params = params.dup
|
||||||
|
|
||||||
begin
|
begin
|
||||||
response = @connection.request(params, &block)
|
response = @connection.request(params, &block)
|
||||||
rescue Excon::Errors::TemporaryRedirect => error
|
rescue Excon::Errors::TemporaryRedirect => error
|
||||||
uri = URI.parse(error.response.is_a?(Hash) ? error.response[:headers]['Location'] : error.response.headers['Location'])
|
headers = (error.response.is_a?(Hash) ? error.response[:headers] : error.response.headers)
|
||||||
|
uri = URI.parse(headers['Location'])
|
||||||
Fog::Logger.warning("fog: followed redirect to #{uri.host}, connecting to the matching region will be more performant")
|
Fog::Logger.warning("fog: followed redirect to #{uri.host}, connecting to the matching region will be more performant")
|
||||||
response = Fog::Connection.new("#{@scheme}://#{uri.host}:#{@port}", false, @connection_options).request(original_params, &block)
|
response = Fog::Connection.new("#{@scheme}://#{uri.host}:#{@port}", false, @connection_options).request(original_params, &block)
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ Shindo.tests("Storage[:aws] | directory", ["aws"]) do
|
||||||
@instance.save
|
@instance.save
|
||||||
|
|
||||||
tests("#public_url").returns(true) do
|
tests("#public_url").returns(true) do
|
||||||
if @instance.public_url =~ %r[\Ahttps://fogdirectorytests-[\da-f]+\.s3\.amazonaws\.com\z]
|
if @instance.public_url =~ %r[\Ahttps://fogdirectorytests-[\da-f]+\.s3\.amazonaws\.com/\z]
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
@instance.public_url
|
@instance.public_url
|
||||||
|
|
|
@ -14,15 +14,17 @@ Shindo.tests('AWS | url', ["aws"]) do
|
||||||
@file = @storage.directories.new(:key => 'fognonbucket').files.new(:key => 'test.txt')
|
@file = @storage.directories.new(:key => 'fognonbucket').files.new(:key => 'test.txt')
|
||||||
|
|
||||||
if Fog.mock?
|
if Fog.mock?
|
||||||
signature = Fog::Storage::AWS.new.signature(nil)
|
signature = Fog::Storage::AWS.new.signature(nil, nil)
|
||||||
else
|
else
|
||||||
signature = 'tajHIhKHAdFYsigmzybCpaq8N0Q%3D'
|
signature = 'tajHIhKHAdFYsigmzybCpaq8N0Q%3D'
|
||||||
end
|
end
|
||||||
|
|
||||||
tests('#url w/ response-cache-control').returns(
|
if RUBY_VERSION > '1.8.7' # ruby 1.8.x doesn't provide hash ordering
|
||||||
"https://fognonbucket.s3.amazonaws.com/test.txt?response-cache-control=No-cache&AWSAccessKeyId=123&Signature=#{signature}&Expires=1356998400"
|
tests('#url w/ response-cache-control').returns(
|
||||||
) do
|
"https://fognonbucket.s3.amazonaws.com/test.txt?response-cache-control=No-cache&AWSAccessKeyId=123&Signature=#{signature}&Expires=1356998400"
|
||||||
@file.url(@expires, :query => { 'response-cache-control' => 'No-cache' })
|
) do
|
||||||
|
@file.url(@expires, :query => { 'response-cache-control' => 'No-cache' })
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue