Skip to content

Instantly share code, notes, and snippets.

@nowk
Last active December 20, 2015 06:39
Show Gist options
  • Save nowk/6087021 to your computer and use it in GitHub Desktop.
Save nowk/6087021 to your computer and use it in GitHub Desktop.
Amazon S3 request generator class
class AwsS3
AWS_ACCESS_KEY = ENV['AWS_ACCESS_KEY_ID']
AWS_SECRET_KEY = ENV['AWS_SECRET_ACCESS_KEY']
S3_BUCKET = ENV['S3_BUCKET'] || "#{Rails.application.class.parent_name}_#{Rails.env}".downcase
attr_accessor :file_name, :mime_type, :path, :acl, :expires_in
attr_writer :as_attachment
def initialize(file_name, mime_type, acl: 'private', path: '/')
@file_name = esc file_name # escape for spaces and the like
@mime_type = mime_type
@acl = acl
@path = path
end
# NOTE why we use non subdomain uris http://stackoverflow.com/questions/5208851/is-there-a-workaround-to-open-urls-containing-underscores-in-ruby
def self.base_url
"https://s3.amazonaws.com/#{S3_BUCKET}"
end
def base_url
self.class.base_url
end
def file_path
fp = File.join(path, file_name).gsub /^\//, '' # remove leading /
return fp+"?response-content-disposition=attachment" if as_attachment?
fp
end
def url
File.join(base_url, file_path)
end
def expires_in
@expires_in ||= 60.minutes.from_now.to_i
end
def as_attachment?
@as_attachment == true
end
def method_missing(method, *args, &block)
if method.to_s =~ /^(get|put|delete)_signature$/
esc Base64.encode64(OpenSSL::HMAC
.digest(sha1, AWS_SECRET_KEY, __send__("#{$1}_request"))).gsub("\n","")
elsif method.to_s =~ /^(get|put|delete)_signed_request(!)?$/
_url = [
url,
%{#{key_and_expires_params}&Signature=#{__send__("#{$1}_signature")}}
].join(as_attachment? ? '&' : '?')
$2 == '!' ? esc(_url) : _url
else
super
end
end
def respond_to?(meth, include_private: false)
return true if meth =~ /^(get|put|delete)_signature$/
return true if meth =~ /^(get|put|delete)_signed_request(!)?$/
super
end
private
def key_and_expires_params
"AWSAccessKeyId=#{AWS_ACCESS_KEY}&Expires=#{expires_in}"
end
def amz_acl_header
"x-amz-acl:#{acl}"
end
def amz_date_header
"x-amz-date:#{expires_in}"
end
def bucket_file_path
"/#{S3_BUCKET}/#{file_path}"
end
def put_request
['PUT', '', mime_type, expires_in, amz_acl_header, bucket_file_path].join("\n").encode('UTF-8')
end
def get_request
['GET', '', '', expires_in, bucket_file_path].join("\n").encode('UTF-8')
end
def delete_request
['DELETE', '', '', expires_in, bucket_file_path].join("\n").encode('UTF-8')
end
def sha1
OpenSSL::Digest::Digest.new('sha1')
end
def esc(val)
CGI.escape val
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment