Class: AwsProductSign
- Inherits:
-
Object
- Object
- AwsProductSign
- Defined in:
- lib/aws_product_sign.rb
Overview
Then you can go on to use those new params in rails url_for or the URI
builder of your choice. Values are not URI-escaped yet. Or mutate the
params passsed in with #add_signature! instead.
Returning a new params hash, leaving your input untouched:
query_string_component = aws_signer.add_signature( params )
Or mutate your input:
aws_signer.add_signature!(params)
At the moment this class can’t handle a query string where you need the same key twice. I don’t think the AWS service ever uses that though?
This class also assumes a GET request.
Instance Method Summary collapse
- #access_key ⇒ Object
- #access_key=(a) ⇒ Object
-
#add_signature(params) ⇒ Object
Pass in a hash representing params for a query string.
-
#add_signature!(params) ⇒ Object
Like #add_signature, but will mutate the hash passed in, adding a “Signature” key/value to hash passed in, and return hash too.
-
#canonical_querystring(params) ⇒ Object
param keys should be strings, not symbols please.
-
#hash_to_query(hash) ⇒ Object
Turns a hash into a query string, returns the query string.
-
#initialize(options = {}) ⇒ AwsProductSign
constructor
A new instance of AwsProductSign.
- #query_with_signature(hash) ⇒ Object
- #secret_key ⇒ Object
- #string_to_sign(query_string, options = {}) ⇒ Object
-
#url_encode(string) ⇒ Object
Insist on specific method of URL encoding, RFC3986.
Constructor Details
#initialize(options = {}) ⇒ AwsProductSign
Returns a new instance of AwsProductSign.
51 52 53 54 55 |
# File 'lib/aws_product_sign.rb', line 51 def initialize( = {}) @secret_key = [:secret_key] raise Exception.new("You must supply a :secret_key") unless @secret_key @access_key = [:access_key] end |
Instance Method Details
#access_key ⇒ Object
139 140 141 |
# File 'lib/aws_product_sign.rb', line 139 def access_key return @access_key end |
#access_key=(a) ⇒ Object
142 143 144 |
# File 'lib/aws_product_sign.rb', line 142 def access_key=(a) @access_key = a end |
#add_signature(params) ⇒ Object
Pass in a hash representing params for a query string.
param keys should be strings, not symbols please. Will return a param with the “Signature” key/value added, without modifying original.
65 66 67 68 |
# File 'lib/aws_product_sign.rb', line 65 def add_signature(params) # Make a copy to not modify original add_signature!( Hash[params] ) end |
#add_signature!(params) ⇒ Object
Like #add_signature, but will mutate the hash passed in, adding a “Signature” key/value to hash passed in, and return hash too.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/aws_product_sign.rb', line 73 def add_signature!(params) # supply timestamp and access key if not already provided params["Timestamp"] ||= Time.now.iso8601 params["AWSAccessKeyId"] ||= access_key # Existing "Signature"? That's gotta go before we generate a new # signature and add it. params.delete("Signature") query_string = canonical_querystring(params) string_to_sign = string_to_sign(query_string) # chomp is important! the base64 encoded version will have a newline at the end # which amazon does not want. digest = OpenSSL::Digest.new('sha256') signature = Base64.encode64(OpenSSL::HMAC.digest(digest, secret_key, string_to_sign)).chomp params["Signature"] = signature #order doesn't matter for the actual request, we return the hash #and let client turn it into a url. return params end |
#canonical_querystring(params) ⇒ Object
param keys should be strings, not symbols please. return a string joined by & in canonical order.
107 108 109 110 111 112 |
# File 'lib/aws_product_sign.rb', line 107 def canonical_querystring(params) # I hope this built-in sort sorts by byte order, that's what's required. values = params.keys.sort.collect {|key| [url_encode(key), url_encode(params[key].to_s)].join("=") } return values.join("&") end |
#hash_to_query(hash) ⇒ Object
Turns a hash into a query string, returns the query string. url-encodes everything to Amazon’s specifications.
128 129 130 131 132 133 134 |
# File 'lib/aws_product_sign.rb', line 128 def hash_to_query(hash) hash.collect do |key, value| url_encode(key) + "=" + url_encode(value) end.join("&") end |
#query_with_signature(hash) ⇒ Object
57 58 59 |
# File 'lib/aws_product_sign.rb', line 57 def query_with_signature(hash) return hash_to_query( add_signature(hash) ) end |
#secret_key ⇒ Object
136 137 138 |
# File 'lib/aws_product_sign.rb', line 136 def secret_key return @secret_key end |
#string_to_sign(query_string, options = {}) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/aws_product_sign.rb', line 114 def string_to_sign(query_string, = {}) [:verb] = "GET" [:request_uri] = "/onca/xml" [:host] = "webservices.amazon.com" return [:verb] + "\n" + [:host].downcase + "\n" + [:request_uri] + "\n" + query_string end |
#url_encode(string) ⇒ Object
Insist on specific method of URL encoding, RFC3986.
99 100 101 102 103 |
# File 'lib/aws_product_sign.rb', line 99 def url_encode(string) # It's kinda like CGI.escape, except CGI.escape is encoding a tilde when # it ought not to be, so we turn it back. Also space NEEDS to be %20 not +. return CGI.escape(string).gsub("%7E", "~").gsub("+", "%20") end |