Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to S3's GET link with response-* params #47

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/awsbase/right_awsbase.rb
Expand Up @@ -121,6 +121,16 @@ def self.URLencode(raw)
e.gsub(/\+/, "%2b")
end

def self.CGIescape(raw)
e = CGI::escape raw
e.gsub(/\+/, "%20")
end

def self.CGIunescape(escaped)
r = escaped.gsub("%20", "+")
CGI::unescape r
end

def self.allow_only(allowed_keys, params)
bogus_args = []
params.keys.each {|p| bogus_args.push(p) unless allowed_keys.include?(p) }
Expand Down
80 changes: 79 additions & 1 deletion lib/awsbase/support.rb
Expand Up @@ -31,5 +31,83 @@ class String #:nodoc:
def right_underscore
self.gsub(/[A-Z]/){|match| "#{$`=='' ? '' : '_'}#{match.downcase}" }
end


# Constantize tries to find a declared constant with the name specified
# in the string. It raises a NameError when the name is not in CamelCase
# or is not initialized.
#
# Examples
# "Module".constantize #=> Module
# "Class".constantize #=> Class
def right_constantize()
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
raise NameError, "#{self.inspect} is not a valid constant name!"
end
Object.module_eval("::#{$1}", __FILE__, __LINE__)
end

def right_camelize()
self.dup.split(/_/).map{ |word| word.capitalize }.join('')
end

end


class Object #:nodoc:
# "", " ", nil, [], and {} are blank
def right_blank?
if respond_to?(:empty?) && respond_to?(:strip)
empty? or strip.empty?
elsif respond_to?(:empty?)
empty?
else
!self
end
end
end

class NilClass #:nodoc:
def right_blank?
true
end
end

class FalseClass #:nodoc:
def right_blank?
true
end
end

class TrueClass #:nodoc:
def right_blank?
false
end
end

class Array #:nodoc:
alias_method :right_blank?, :empty?
end

class Hash #:nodoc:
alias_method :right_blank?, :empty?

# Return a new hash with all keys converted to symbols.
def right_symbolize_keys
inject({}) do |options, (key, value)|
options[key.to_sym] = value
options
end
end
end

class String #:nodoc:
def right_blank?
empty? || strip.empty?
end
end

class Numeric #:nodoc:
def right_blank?
false
end
end
36 changes: 34 additions & 2 deletions lib/s3/right_s3_interface.rb
Expand Up @@ -114,6 +114,16 @@ def canonical_string(method, path, headers={}, expires=nil) # :nodoc:
out_string << '?torrent' if path[/[&?]torrent($|&|=)/]
out_string << '?location' if path[/[&?]location($|&|=)/]
out_string << '?logging' if path[/[&?]logging($|&|=)/] # this one is beta, no support for now
if method == 'GET'
# fetch all response-* param pairs recursively (dirty method)
while path[/[&?](response\-[A-Za-z\-]+=[^&]+)($|&)/]
resp = $1
# string-to-sign must be un-encoded, so an unescape process is taken on resp,
# which is already escaped in get_link()
out_string << ("#{out_string[/\?/] ? "&" : "?"}#{AwsUtils.CGIunescape(resp)}")
path = path.gsub(/[&?]#{resp}/, '')
end
end
out_string
end

Expand Down Expand Up @@ -916,8 +926,30 @@ def put_link(bucket, key, data=nil, expires=nil, headers={})
# s3.get_link('my_awesome_bucket',key) #=> https://s3.amazonaws.com:443/my_awesome_bucket/asia%2Fcustomers?Signature=QAO...
#
# see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html
def get_link(bucket, key, expires=nil, headers={})
generate_link('GET', headers.merge(:url=>"#{bucket}/#{CGI::escape key}"), expires)
#
# To specify +response+-* parameters, gather them together in a hash at the 5th parameter,
# with +expires+ set to +nil+ and +headers+ to {} (or whatever values you want):
#
# s3.get_link('my_awesome_bucket', key, nil, {}, {
# "response-content-disposition" => "attachment; filename=café.png", # supports non-ascii chars
# "response-content-type" => "image/png"})
# #=> https://s3.amazonaws.com:443/my_awesome_bucket/asia%2Fcustomers?response-content-disposition=attachment%3B%20filename%3Dcaf%25C3%25A9.png
# &response-content-type=image%2Fpng&Signature=wio...
def get_link(bucket, key, expires=nil, headers={}, response_params={})
if response_params == {} || response_params == nil
generate_link('GET', headers.merge(:url=>"#{bucket}/#{CGI::escape key}"), expires)
else
params_s = response_params.sort { |a,b| a[0] <=> b[0] }.map { |x|
if (x[0] == 'response-content-disposition')
if (x[1][/(.+filename=)(.+)/])
# escape the filename with "+" being replaced with "%20" to avoid enconding issue on non-ascii chars
x[1] = "#{$1}#{AwsUtils.CGIescape($2)}"
end
end
"#{x[0]}=#{AwsUtils.CGIescape(x[1])}" # collect escaped parameters
}.join('&')
generate_link('GET', headers.merge(:url=>"#{bucket}/#{CGI::escape key}?#{params_s}"), expires)
end
rescue
on_exception
end
Expand Down