Following the instructions in this guide, I've managed to get uploads working via signed URLs. It looks something like this:
const s3 = new aws.S3(); const s3Params = { Bucket: S3_BUCKET, Key: fileName, Expires: 60, ContentType: fileType, ACL: 'public-read', CacheControl: 'public, max-age=31536000', }; s3.getSignedUrl('putObject', s3Params, (err, data) => { // ... });
...except my CacheControl
param (which I added myself; it isn't in the guide) does not seem to take effect. When I use the above code to generate a signed URL and upload something to it, the resulting object in S3 is served with no Cache-Control
header.
What am I doing wrong?
1 Answers
Answers 1
You must send the Cache-Control
header in the upload request, regardless of what you set during the signed URL generation.
Whether this is a bug or an intentional behaviour is questionable and beyond my ability to answer. The Cache-Control
header, as you noticed, is part of the signed URL, but for whatever reason the information is completely ignored during the file upload, ie. not specifying a CacheControl
property in the getSignedUrl()
function still allows the client to set Cache-Control
header to whatever value they choose.
If you need to have control over the Cache-Control
header, then using the getSignedUrl()
is most likely not appropriate for your use case.
Solution
AWS now supports a new signature scheme, called AWS Signature version 4 which allows full control over what the upload request may or may not contain, including which headers are sent and with what values.
The JavaScript SDK supports this new signature version: createPresignedPost()
.
A detailed example of how to generate this pre-signed POST
policy and how the upload form should look like can be found directly on AWS's documentation.
Even though the example demonstrates the file upload via standard http upload <form>
element, the principles can be applied to any client/consumer capable of performing HTTP communication.
Example
For completeness, here is the example (taken from AWS documentation page linked above) of how a pre-signed POST
policy looks like:
{ "expiration": "2015-12-30T12:00:00.000Z", "conditions": [ {"bucket": "sigv4examplebucket"}, ["starts-with", "$key", "user/user1/"], {"acl": "public-read"}, {"success_action_redirect": "http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html"}, ["starts-with", "$Content-Type", "image/"], {"x-amz-meta-uuid": "14365123651274"}, {"x-amz-server-side-encryption": "AES256"}, ["starts-with", "$x-amz-meta-tag", ""], {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request"}, {"x-amz-algorithm": "AWS4-HMAC-SHA256"}, {"x-amz-date": "20151229T000000Z" } ] }
This POST policy sets the following conditions on the request:
- The upload must occur before midnight UTC on December 30, 2015.
- The content can be uploaded only to the
sigv4examplebucket
. The bucket must be in the region that you specified in the credential scope (x-amz-credential
form parameter), because the signature you provided is valid only within this scope. - You can provide any key name that starts with
user/user1
. For example,user/user1/MyPhoto.jpg
. - The ACL must be set to
public-read
. - If the upload succeeds, the user's browser is redirected to
http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html
. - The object must be an image file.
- The
x-amz-meta-uuid
tag must be set to14365123651274
. - The
x-amz-meta-tag
can contain any value.
Note that the list of conditions in this example is not exhaustive and CacheControl
is supported. See the creating a POST policy document for what you can do with this.
0 comments:
Post a Comment