最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to define the Cache-Control header on an S3 object via a signed URL? - Stack Overflow

programmeradmin5浏览0评论

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?

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?

Share Improve this question edited Jun 21, 2017 at 10:29 callum asked Apr 20, 2017 at 16:49 callumcallum 37.8k39 gold badges113 silver badges175 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 14 +300

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 pletely 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 munication.

Example

For pleteness, 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./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./successful_upload.html.
  • The object must be an image file.
  • The x-amz-meta-uuid tag must be set to 14365123651274.
  • 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.

Contrary to what the accepted answer says, you can add Cache-Control to the URL obtained from the getSignedURL, but only for the getObject operation. I hope this helps people who came here for getObject.

This is what I have done

    const params = {
      Bucket: <YOUR_S3_BUCKET>,
      Key: <YOUR_KEY>,
      ResponseCacheControl: `public, max-age=900, immutable`,
      Expires: 900 // default value
    }

    return this.S3.getSignedUrl('getObject', params)

The resulting URL looks like this

https://<YOUR_S3_BUCKET>.s3.us-east-2.amazonaws./<YOUR_KEY>?...&response-cache-control=public%2C%20max-age%3D900%2C%20immutable

and the response header Cache-Control: public, max-age=900, immutable

Check out the doc here and notice the params in the last example. You can find the ResponseCacheControl and Expires params there.

If you look at the docs, you can see that putObject contains the CacheControl param but adding that to params does not do anything.

发布评论

评论列表(0)

  1. 暂无评论