Last active
December 20, 2015 06:39
-
-
Save nowk/6087021 to your computer and use it in GitHub Desktop.
Amazon S3 request generator class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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