Class: AWS::S3::PresignedPost

Inherits:
Object
  • Object
show all
Includes:
Core::Model
Defined in:
lib/aws/s3/presigned_post.rb

Overview

Helper to generate form fields for presigned POST requests to a bucket. You can use this to create a form that can be used from a web browser to upload objects to S3 while specifying conditions on what can be uploaded and how it is processed and stored.

Examples:

Form fields for uploading by file name


form = bucket.presigned_post(:key => "photos/${filename}")
form.url.to_s        # => "https://mybucket.s3.amazonaws.com/"
form.fields          # => { "AWSAccessKeyId" => "...", ... }

Generating a minimal HTML form


form = bucket.objects.myobj.presigned_post
hidden_inputs = form.fields.map do |(name, value)|
  %(<input type="hidden" name="#{name}" value="#{value}" />)
end
<<-END
<form action="#{form.url}" method="post" enctype="multipart/form-data">
  #{hidden_inputs}
  <input type="file" name="file" />
</form>
END

Restricting the size of the uploaded object

bucket.presigned_post(:content_length => 1..(10*1024))

Restricting the key prefix

bucket.presigned_post.where(:key).starts_with("photos/")

Defined Under Namespace

Classes: ConditionBuilder

Constant Summary collapse

SPECIAL_FIELDS =
[:cache_control,
:content_type,
:content_disposition,
:content_encoding,
:expires_header,
:acl,
:server_side_encryption,
:success_action_redirect,
:success_action_status]

Instance Attribute Summary collapse

Attributes included from Core::Model

#config

Instance Method Summary collapse

Methods included from Core::Model

#client, #config_prefix, #inspect

Constructor Details

#initialize(bucket, opts = {}) ⇒ PresignedPost

Creates a new presigned post object.

Parameters:

  • bucket (Bucket)

    The bucket to which data can be uploaded using the form fields.

  • opts (Hash) (defaults to: {})

    Additional options for the upload. Aside from :secure, :expires, :content_length and :ignore the values provided here will be stored in the hash returned from the #fields method, and the policy in that hash will restrict their values to the values provided. If you instead want to only restrict the values and not provide them – for example, if your application generates separate form fields for those values – you should use the #where method on the returned object instead of providing the values here.

  • options (Hash)

    a customizable set of options

Options Hash (opts):

  • :key (String)

    The key of the object that will be uploaded. If this is nil, then the object can be uploaded with any key that satisfies the conditions specified for the upload (see #where).

  • :secure (Boolean)

    By setting this to false, you can cause #url to return an HTTP URL. By default it returns an HTTPS URL.

  • :expires (Time, DateTime, Integer, String)

    The time at which the signature will expire. By default the signature will expire one hour after it is generated (e.g. when #fields is called).

    When the value is a Time or DateTime, the signature expires at the specified time. When it is an integer, the signature expires the specified number of seconds after it is generated. When it is a string, the string is parsed as a time (using Time.parse) and the signature expires at that time.

  • :cache_control (String)

    Sets the Cache-Control header stored with the object.

  • :content_type (String)

    Sets the Content-Type header stored with the object.

  • :content_disposition (String)

    Sets the Content-Disposition header stored with the object.

  • :expires_header (String)

    Sets the Expires header stored with the object.

  • :success_action_redirect (String)

    The URL to which the client is redirected upon successful upload.

  • :success_action_status (Integer)

    The status code returned to the client upon successful upload if :success_action_redirect is not specified. Accepts the values 200, 201, or 204 (default).

    If the value is set to 200 or 204, Amazon S3 returns an empty document with a 200 or 204 status code.

    If the value is set to 201, Amazon S3 returns an XML document with a 201 status code. For information on the content of the XML document, see POST Object.

  • :metadata (Hash)

    A hash of the metadata fields included in the signed fields. Additional metadata fields may be provided with the upload as long as they satisfy the conditions specified for the upload (see #where).

  • :content_length (Integer, Range)

    The range of acceptable object sizes for the upload. By default any size object may be uploaded.

  • :ignore (Array<String>)

    Additional fields which may be sent with the upload. These will be included in the policy so that they can be sent with any value. S3 will ignore them.



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/aws/s3/presigned_post.rb', line 196

def initialize(bucket, opts = {})
  @bucket = bucket
  @key = opts[:key]
  @secure = (opts[:secure] != false)
  @fields = {}
  SPECIAL_FIELDS.each do |name|
    @fields[name] = opts[name] if opts.key?(name)
  end
  @metadata = opts[:metadata] || {}
  @content_length = range_value(opts[:content_length])
  @conditions = opts[:conditions] || {}
  @ignored_fields = [opts[:ignore]].flatten.compact
  @expires = opts[:expires]

  super

  @fields[:server_side_encryption] =
    config.s3_server_side_encryption unless
    @fields.key?(:server_side_encryption)
  @fields.delete(:server_side_encryption) if
    @fields[:server_side_encryption].nil?
end

Instance Attribute Details

#bucketBucket (readonly)

Returns The bucket to which data can be uploaded using the form fields.

Returns:

  • (Bucket)

    The bucket to which data can be uploaded using the form fields



58
59
60
# File 'lib/aws/s3/presigned_post.rb', line 58

def bucket
  @bucket
end

#conditionsObject (readonly)



88
89
90
# File 'lib/aws/s3/presigned_post.rb', line 88

def conditions
  @conditions
end

#content_lengthRange (readonly)

Returns The range of acceptable object sizes for the upload. By default any size object may be uploaded.

Returns:

  • (Range)

    The range of acceptable object sizes for the upload. By default any size object may be uploaded.



74
75
76
# File 'lib/aws/s3/presigned_post.rb', line 74

def content_length
  @content_length
end

#expiresObject (readonly)

Returns The expiration time for the signature. By default the signature will expire an hour after it is generated.

Returns:

  • The expiration time for the signature. By default the signature will expire an hour after it is generated.



98
99
100
# File 'lib/aws/s3/presigned_post.rb', line 98

def expires
  @expires
end

#ignored_fieldsArray<String> (readonly)

Returns Additional fields which may be sent with the upload. These will be included in the policy so that they can be sent with any value. S3 will ignore them.

Returns:

  • (Array<String>)

    Additional fields which may be sent with the upload. These will be included in the policy so that they can be sent with any value. S3 will ignore them.



94
95
96
# File 'lib/aws/s3/presigned_post.rb', line 94

def ignored_fields
  @ignored_fields
end

#keyString (readonly)

Returns The key of the object that will be uploaded. If this is nil, then the object can be uploaded with any key that satisfies the conditions specified for the upload (see #where).

Returns:

  • (String)

    The key of the object that will be uploaded. If this is nil, then the object can be uploaded with any key that satisfies the conditions specified for the upload (see #where).



64
65
66
# File 'lib/aws/s3/presigned_post.rb', line 64

def key
  @key
end

#metadataHash (readonly)

Returns A hash of the metadata fields included in the signed fields. Additional metadata fields may be provided with the upload as long as they satisfy the conditions specified for the upload (see #where).

Returns:

  • (Hash)

    A hash of the metadata fields included in the signed fields. Additional metadata fields may be provided with the upload as long as they satisfy the conditions specified for the upload (see #where).



70
71
72
# File 'lib/aws/s3/presigned_post.rb', line 70

def 
  @metadata
end

Instance Method Details

#fieldsHash

Returns A collection of form fields (including a signature and a policy) that can be used to POST data to S3. Additional form fields may be added after the fact as long as they are described by a policy condition (see #where).

Returns:

  • (Hash)

    A collection of form fields (including a signature and a policy) that can be used to POST data to S3. Additional form fields may be added after the fact as long as they are described by a policy condition (see #where).



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/aws/s3/presigned_post.rb', line 343

def fields

  signature = config.signer.sign(policy, "sha1")

  fields = {
    "AWSAccessKeyId" => config.signer.access_key_id,
    "key" => key,
    "policy" => policy,
    "signature" => signature
  }.merge(optional_fields)

  fields["x-amz-security-token"] = config.signer.session_token if
    config.signer.session_token

  fields.merge(optional_fields)

end

#policyString

Returns The Base64-encoded JSON policy document.

Returns:

  • (String)

    The Base64-encoded JSON policy document.



330
331
332
333
334
335
336
# File 'lib/aws/s3/presigned_post.rb', line 330

def policy
  json = {
    "expiration" => format_expiration,
    "conditions" => generate_conditions
  }.to_json
  Base64.encode64(json).tr("\n","")
end

#refine(opts) ⇒ Object



375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/aws/s3/presigned_post.rb', line 375

def refine(opts)
  self.class.new(bucket, {
                   :conditions => conditions,
                   :key => key,
                   :metadata => ,
                   :secure => secure?,
                   :content_length => content_length,
                   :expires => expires,
                   :ignore => ignored_fields
                 }.merge(@fields).
                 merge(opts))
end

#secure?Boolean

Returns True if #url generates an HTTPS url.

Returns:

  • (Boolean)

    True if #url generates an HTTPS url.



220
221
222
# File 'lib/aws/s3/presigned_post.rb', line 220

def secure?
  @secure
end

#urlURI::HTTP, URI::HTTPS

Returns The URL to which the form fields should be POSTed. If you are using the fields in an HTML form, this is the URL to put in the action attribute of the form tag.

Returns:

  • (URI::HTTP, URI::HTTPS)

    The URL to which the form fields should be POSTed. If you are using the fields in an HTML form, this is the URL to put in the action attribute of the form tag.



228
229
230
231
232
233
# File 'lib/aws/s3/presigned_post.rb', line 228

def url
  req = Request.new
  req.bucket = bucket.name
  req.host = config.s3_endpoint
  build_uri(req)
end

#where(field) ⇒ ConditionBuilder

Adds a condition to the policy for the POST. Use #where_metadata to add metadata conditions.

Examples:

Restricting the ACL to “bucket-owner” ACLs

presigned_post.where(:acl).starts_with("bucket-owner")

Parameters:

  • field (Symbol)

    The field for which a condition should be added. Valid values:

    • :key

    • :content_length

    • :cache_control

    • :content_type

    • :content_disposition

    • :content_encoding

    • :expires_header

    • :acl

    • :success_action_redirect

    • :success_action_status

Returns:

  • (ConditionBuilder)

    An object that allows you to specify a condition on the field.

Raises:

  • (ArgumentError)


306
307
308
309
310
311
# File 'lib/aws/s3/presigned_post.rb', line 306

def where(field)
  raise ArgumentError.new("unrecognized field name #{field}") unless
    [:key, :content_length, *SPECIAL_FIELDS].include?(field) or
    field =~ /^x-amz-meta-/
  ConditionBuilder.new(self, field)
end

#where_metadata(field) ⇒ ConditionBuilder

Adds a condition to the policy for the POST to constrain the values of metadata fields uploaded with the object. If a metadata field does not have a condition associated with it and is not specified in the constructor (see #metadata) then S3 will reject it.

Parameters:

  • field (Symbol, String)

    The name of the metadata attribute. For example, :color corresponds to the “x-amz-meta-color” field in the POST body.

Returns:

  • (ConditionBuilder)

    An object that allows you to specify a condition on the metadata attribute.



325
326
327
# File 'lib/aws/s3/presigned_post.rb', line 325

def (field)
  where("x-amz-meta-#{field}")
end

#with_equality_condition(option_name, value) ⇒ Object



362
363
364
365
# File 'lib/aws/s3/presigned_post.rb', line 362

def with_equality_condition(option_name, value)
  field_name = field_name(option_name)
  with_condition(option_name, Hash[[[field_name, value]]])
end

#with_prefix_condition(option_name, prefix) ⇒ Object



368
369
370
371
372
# File 'lib/aws/s3/presigned_post.rb', line 368

def with_prefix_condition(option_name, prefix)
  field_name = field_name(option_name)
  with_condition(option_name,
                 ["starts-with", "$#{field_name}", prefix])
end