Class: FasterS3Url::BuilderWithNewEscape
- Inherits:
-
Object
- Object
- FasterS3Url::BuilderWithNewEscape
- Defined in:
- lib/faster_s3_url/builder_with_new_escape.rb
Overview
Signing algorithm based on Amazon docs at docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html , as well as some interactive code reading of Aws::Sigv4::Signer github.com/aws/aws-sdk-ruby/blob/6114bc9692039ac75c8292c66472dacd14fa6f9a/gems/aws-sigv4/lib/aws-sigv4/signer.rb as used by Aws::S3::Presigner github.com/aws/aws-sdk-ruby/blob/6114bc9692039ac75c8292c66472dacd14fa6f9a/gems/aws-sdk-s3/lib/aws-sdk-s3/presigner.rb
Constant Summary collapse
- FIFTEEN_MINUTES =
60 * 15
- ONE_WEEK =
60 * 60 * 24 * 7
- SIGNED_HEADERS =
"host".freeze
- METHOD =
"GET".freeze
- ALGORITHM =
"AWS4-HMAC-SHA256".freeze
- SERVICE =
"s3".freeze
- DEFAULT_EXPIRES_IN =
15 minutes, seems to be AWS SDK default
FIFTEEN_MINUTES
- MAX_CACHED_SIGNING_KEYS =
5
Instance Attribute Summary collapse
-
#access_key_id ⇒ Object
readonly
Returns the value of attribute access_key_id.
-
#bucket_name ⇒ Object
readonly
Returns the value of attribute bucket_name.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#region ⇒ Object
readonly
Returns the value of attribute region.
Instance Method Summary collapse
-
#initialize(bucket_name:, region:, access_key_id:, secret_access_key:, host: nil, default_public: true, cache_signing_keys: false) ⇒ BuilderWithNewEscape
constructor
A new instance of BuilderWithNewEscape.
-
#presigned_url(key, time: nil, expires_in: DEFAULT_EXPIRES_IN, response_cache_control: nil, response_content_disposition: nil, response_content_encoding: nil, response_content_language: nil, response_content_type: nil, response_expires: nil, version_id: nil) ⇒ Object
Generates a presigned GET URL for a specified S3 object key.
- #public_url(key) ⇒ Object
-
#url(key, public: @default_public, **options) ⇒ Object
just a convenience method that can call public_url or presigned_url based on flag.
Constructor Details
#initialize(bucket_name:, region:, access_key_id:, secret_access_key:, host: nil, default_public: true, cache_signing_keys: false) ⇒ BuilderWithNewEscape
Returns a new instance of BuilderWithNewEscape.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 41 def initialize(bucket_name:, region:, access_key_id:, secret_access_key:, host:nil, default_public: true, cache_signing_keys: false) @bucket_name = bucket_name @region = region @host = host || default_host(bucket_name) @default_public = default_public @access_key_id = access_key_id @secret_access_key = secret_access_key @cache_signing_keys = cache_signing_keys if @cache_signing_keys @signing_key_cache = {} end @canonical_headers = "host:#{@host}\n" end |
Instance Attribute Details
#access_key_id ⇒ Object (readonly)
Returns the value of attribute access_key_id.
23 24 25 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 23 def access_key_id @access_key_id end |
#bucket_name ⇒ Object (readonly)
Returns the value of attribute bucket_name.
23 24 25 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 23 def bucket_name @bucket_name end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
23 24 25 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 23 def host @host end |
#region ⇒ Object (readonly)
Returns the value of attribute region.
23 24 25 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 23 def region @region end |
Instance Method Details
#presigned_url(key, time: nil, expires_in: DEFAULT_EXPIRES_IN, response_cache_control: nil, response_content_disposition: nil, response_content_encoding: nil, response_content_language: nil, response_content_type: nil, response_expires: nil, version_id: nil) ⇒ Object
Generates a presigned GET URL for a specified S3 object key.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 88 def presigned_url(key, time: nil, expires_in: DEFAULT_EXPIRES_IN, response_cache_control: nil, response_content_disposition: nil, response_content_encoding: nil, response_content_language: nil, response_content_type: nil, response_expires: nil, version_id: nil) validate_expires_in(expires_in) canonical_uri = "/" + uri_escape_key(key) now = time ? time.dup.utc : Time.now.utc # Uh Time#utc is mutating, not nice to do to an argument! amz_date = now.strftime("%Y%m%dT%H%M%SZ") datestamp = now.strftime("%Y%m%d") credential_scope = datestamp + '/' + region + '/' + SERVICE + '/' + 'aws4_request' canonical_query_string_parts = [ "X-Amz-Algorithm=#{ALGORITHM}", "X-Amz-Credential=" + uri_escape(@access_key_id + "/" + credential_scope), "X-Amz-Date=" + amz_date, "X-Amz-Expires=" + expires_in.to_s, "X-Amz-SignedHeaders=" + SIGNED_HEADERS, ] extra_params = { :"response-cache-control" => response_cache_control, :"response-content-disposition" => response_content_disposition, :"response-content-encoding" => response_content_encoding, :"response-content-language" => response_content_language, :"response-content-type" => response_content_type, :"response-expires" => (response_expires), :"versionId" => version_id }.compact if extra_params.size > 0 # These have to be sorted, but sort is case-sensitive, and we have a fixed # list of headers we know might be here... turns out they are already sorted? extra_param_parts = extra_params.collect {|k, v| "#{k}=#{uri_escape v}" }.join("&") canonical_query_string_parts << extra_param_parts end canonical_query_string = canonical_query_string_parts.join("&") canonical_request = ["GET", canonical_uri, canonical_query_string, @canonical_headers, SIGNED_HEADERS, 'UNSIGNED-PAYLOAD' ].join("\n") string_to_sign = [ ALGORITHM, amz_date, credential_scope, Digest::SHA256.hexdigest(canonical_request) ].join("\n") signing_key = retrieve_signing_key(datestamp) signature = OpenSSL::HMAC.hexdigest("SHA256", signing_key, string_to_sign) return "https://" + self.host + canonical_uri + "?" + canonical_query_string + "&X-Amz-Signature=" + signature end |
#public_url(key) ⇒ Object
57 58 59 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 57 def public_url(key) "https://#{self.host}/#{uri_escape_key(key)}" end |
#url(key, public: @default_public, **options) ⇒ Object
just a convenience method that can call public_url or presigned_url based on flag
signer.url(object_key, public: true)
#=> forwards to signer.public_url(object_key)
signer.url(object_key, public: false, response_content_type: "image/jpeg")
#=> forwards to signer.presigned_url(object_key, response_content_type: "image/jpeg")
Options (sucn as response_content_type) that are not applicable to #public_url
are ignored in public mode.
The default value of `public` can be set by initializer arg `default_public`, which
is itself default true.
builder = FasterS3Url::Builder.new(..., default_public: false)
builder.url(object_key) # will call #presigned_url
173 174 175 176 177 178 179 |
# File 'lib/faster_s3_url/builder_with_new_escape.rb', line 173 def url(key, public: @default_public, **) if public public_url(key) else presigned_url(key, **) end end |