diff --git a/lib/fog/aws.rb b/lib/fog/aws.rb index 52b073302..14d97c274 100644 --- a/lib/fog/aws.rb +++ b/lib/fog/aws.rb @@ -35,7 +35,7 @@ module Fog @headers.merge!({'Host' => host}) request = "#{method} #{path} HTTP/1.1\r\n" request << "#{headers.collect {|k,v| "#{k}: #{v}\r\n"}.join('')}\r\n" - request << "\r\n#{@body}\r\n" if @body + request << "#{@body}\r\n" if @body send_data(request) end diff --git a/lib/fog/aws/s3.rb b/lib/fog/aws/s3.rb index ff8eb0bca..571cd4f05 100644 --- a/lib/fog/aws/s3.rb +++ b/lib/fog/aws/s3.rb @@ -1,7 +1,9 @@ require 'rubygems' require 'base64' require 'cgi' +require 'digest/md5' require 'hmac-sha1' +require 'mime/types' require 'uri' require File.dirname(__FILE__) + '/s3/parsers' @@ -145,6 +147,18 @@ module Fog ) end + # Create an object in an S3 bucket + def put_object(bucket_name, object_name, object, options = {}) + file = parse_file(object) + request( + 'PUT', + url(bucket_name, object_name), + Fog::Parsers::AWS::S3::BasicParser.new, + options.merge!(file[:headers]), + file[:body] + ) + end + # Copy an object from one S3 bucket to another def copy_object(source_bucket_name, source_object_name, destination_bucket_name, destination_object_name) request( @@ -160,7 +174,7 @@ module Fog request( 'GET', url(bucket_name, object_name), - Fog::Parsers::AWS::S3::BasicParser.new + nil ) end @@ -193,20 +207,46 @@ module Fog end def canonicalize_amz_headers(headers) - headers = headers.select {|key,value| key.match(/^x-amz-/)}.sort {|x,y| x[0] <=> y[0]}.collect {|header| header.join(':')}.join("\n") + headers = headers.select {|key,value| key.match(/^x-amz-/iu)}.sort {|x,y| x[0] <=> y[0]}.collect {|header| header.join(':')}.join("\n").downcase headers.empty? ? nil : headers end + def canonicalize_resource(uri) + resource = "/#{'s3.amazonaws.com' == uri.host ? "" : "#{uri.host.split('.s3.amazonaws.com')[0]}/"}" + resource << "#{uri.path[1..-1]}" if uri.path + resource << "?location" if uri.to_s.include?('?acl') + resource << "?location" if uri.to_s.include?('?location') + resource << "?location" if uri.to_s.include?('?torrent') + resource + end + + def parse_file(file) + metadata = { + :body => nil, + :headers => {} + } + + filename = File.basename(file.path) + unless (mime_types = MIME::Types.of(filename)).empty? + metadata[:headers]['Content-Type'] = mime_types.first.content_type + end + + metadata[:body] = file.read + metadata[:headers]['Content-Length'] = metadata[:body].size.to_s + metadata[:headers]['Content-MD5'] = Base64.encode64(Digest::MD5.digest(metadata[:body])).strip + metadata + end + def request(method, url, parser, headers = {}, data = nil) uri = URI.parse(url) headers['Date'] = Time.now.utc.strftime("%a, %d %b %Y %H:%M:%S +0000") params = [ method, - content_md5 = '', - content_type = '', + content_md5 = headers['Content-MD5'] || '', + content_type = headers['Content-Type'] || '', headers['Date'], canonicalized_amz_headers = canonicalize_amz_headers(headers), - canonicalized_resource = "/#{'s3.amazonaws.com' == uri.host ? "" : "#{uri.host.split('.s3.amazonaws.com')[0]}/"}" + canonicalized_resource = canonicalize_resource(uri) ] string_to_sign = params.delete_if {|value| value.nil?}.join("\n") hmac = @hmac.update(string_to_sign) diff --git a/spec/aws/s3/put_object_spec.rb b/spec/aws/s3/put_object_spec.rb new file mode 100644 index 000000000..a4e1b459a --- /dev/null +++ b/spec/aws/s3/put_object_spec.rb @@ -0,0 +1,20 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +describe 'S3.put_object' do + + before(:all) do + s3.put_bucket('fogputobject') + end + + after(:all) do + s3.delete_object('fogputobject', 'fogputobject') + s3.delete_bucket('fogputobject') + end + + it 'should return proper attributes' do + p 'SHOULD CHECK FOR PROPER ATTRIBUTES' + file = File.open(File.dirname(__FILE__) + '/../../lorem.txt', 'r') + p s3.put_object('fogputobject', 'fogputobject', file) + end + +end \ No newline at end of file diff --git a/spec/lorem.txt b/spec/lorem.txt new file mode 100644 index 000000000..e8b7adfc7 --- /dev/null +++ b/spec/lorem.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file