diff --git a/lib/fog/aws/requests/storage/put_object.rb b/lib/fog/aws/requests/storage/put_object.rb index c60f2c421..42e3e0c77 100644 --- a/lib/fog/aws/requests/storage/put_object.rb +++ b/lib/fog/aws/requests/storage/put_object.rb @@ -17,7 +17,7 @@ module Fog # @option options Expires [String] Cache expiry # @option options x-amz-acl [String] Permissions, must be in ['private', 'public-read', 'public-read-write', 'authenticated-read'] # @option options x-amz-storage-class [String] Default is 'STANDARD', set to 'REDUCED_REDUNDANCY' for non-critical, reproducable data - # @option options x-amz-meta-#{name} Headers to be returned with object, note total size of request without body must be less than 8 KB. + # @option options x-amz-meta-#{name} Headers to be returned with object, note total size of request without body must be less than 8 KB. Each name, value pair must conform to US-ASCII. # # @return [Excon::Response] response: # * headers [Hash]: @@ -25,9 +25,21 @@ module Fog # # @see http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPUT.html + def self.conforming_to_us_ascii!(keys, hash) + return if RUBY_VERSION =~ /^1\.8\./ + keys.each do |k| + v = hash[k] + if !v.encode(::Encoding::US_ASCII, :undef => :replace).eql?(v) + raise Excon::Errors::BadRequest.new("invalid #{k} header: value must be us-ascii") + end + end + end + def put_object(bucket_name, object_name, data, options = {}) data = Fog::Storage.parse_data(data) headers = data[:headers].merge!(options) + self.class.conforming_to_us_ascii! headers.keys.grep(/^x-amz-meta-/), headers + request({ :body => data[:body], :expects => 200, @@ -48,6 +60,8 @@ module Fog define_mock_acl(bucket_name, object_name, options) data = parse_mock_data(data) + headers = data[:headers].merge!(options) + Fog::Storage::AWS::Real.conforming_to_us_ascii! headers.keys.grep(/^x-amz-meta-/), headers bucket = verify_mock_bucket_exists(bucket_name) options['Content-Type'] ||= data[:headers]['Content-Type'] diff --git a/tests/aws/requests/storage/object_tests.rb b/tests/aws/requests/storage/object_tests.rb index a7db795d9..417b53796 100644 --- a/tests/aws/requests/storage/object_tests.rb +++ b/tests/aws/requests/storage/object_tests.rb @@ -1,3 +1,5 @@ +# encoding: utf-8 + Shindo.tests('AWS::Storage | object requests', ['aws']) do @directory = Fog::Storage[:aws].directories.create(:key => 'fogobjecttests-' + Time.now.to_i.to_s(32)) @aws_owner = Fog::Storage[:aws].get_bucket_acl(@directory.key).body['Owner'] @@ -16,6 +18,12 @@ Shindo.tests('AWS::Storage | object requests', ['aws']) do Fog::Storage[:aws].put_object(@directory.identity, 'fog_object', lorem_file) end + if RUBY_VERSION =~ /^1\.8\./ + tests("#put_object('#{@directory.identity}', 'fog_object', lorem_file, {'x-amz-meta-json' => 'ä'}").succeeds do + Fog::Storage[:aws].put_object(@directory.identity, 'fog_object', lorem_file, {'x-amz-meta-json' => 'ä'}) + end + end + tests("#copy_object('#{@directory.identity}', 'fog_object', '#{@directory.identity}', 'fog_other_object')").succeeds do Fog::Storage[:aws].copy_object(@directory.identity, 'fog_object', @directory.identity, 'fog_other_object') end @@ -124,6 +132,12 @@ Shindo.tests('AWS::Storage | object requests', ['aws']) do Fog::Storage[:aws].put_object(fognonbucket, 'fog_non_object', lorem_file) end + unless RUBY_VERSION =~ /^1\.8\./ + tests("#put_object('#{@directory.identity}', 'fog_object', lorem_file, {'x-amz-meta-json' => 'ä'}").raises(Excon::Errors::BadRequest) do + Fog::Storage[:aws].put_object(@directory.identity, 'fog_object', lorem_file, {'x-amz-meta-json' => 'ä'}) + end + end + tests("#copy_object('#{fognonbucket}', 'fog_object', '#{@directory.identity}', 'fog_other_object')").raises(Excon::Errors::NotFound) do Fog::Storage[:aws].copy_object(fognonbucket, 'fog_object', @directory.identity, 'fog_other_object') end