home / tils / til

Menu
  • GraphQL API

til: aws_s3-cors.md

This data as json

path topic title url body html shot created created_utc updated updated_utc shot_hash slug
aws_s3-cors.md aws Adding a CORS policy to an S3 bucket https://github.com/simonw/til/blob/main/aws/s3-cors.md Amazon S3 buckets that are configured to work as public websites can support CORS, allowing assets such as JavaScript modules to be loaded by JavaScript running on other domains. This configuration happens at the bucket level - it's not something that can be applied to individual items. [Here's their documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html). As with so many AWS things it involves hand-crafting a JSON document: the documentation for that format, with useful examples, [is here](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html). I opted to use the S3 web console option - find the bucket in the console interface, click the "Security" tab and you can paste in a JSON configuration. The configuration I tried first was this one: ```json [ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET" ], "AllowedOrigins": [ "https://simonwillison.net/" ], "ExposeHeaders": [] } ] ``` This should enable CORS access for GET requests from code running on my https://simonwillison.net/ site. The `AllowedOrigins` key is interesting: it works by inspecting the `Origin` header on the incoming request, and returning CORS headers based on if that origin matches one of the values in the list. I used `curl -i ... -H "Origin: value"` to confirm that this worked: ``` ~ % curl -i 'http://static.simonwillison.net.s3-website-us-west-1.amazonaws.com/static/2022/photoswipe/photoswipe-lightbox.esm.js' \ -H "Origin: https://simonwillison.net" | head -n 20 -x-amz-request-id: 4YY7ZBCVJ167XCR9 Date: Tue, 04 Jan 2022 21:02:44 GMT -Access-Control-Allow-Origin: * -Access-Control-Allow-Methods: GET :Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method -Last-Modified: Tue, 04 Jan 2022 20:10:26 GMT -ETag: "8e26fa2b966ca8bac30678cdd6af765c" :Content-Type: text/javascript -Server: AmazonS3 ~ % curl -i 'http://static.simonwillison.net.s3-website-us-west-1.amazonaws.com/static/2022/photoswipe/photoswipe-lightbox.esm.js' | head -n 20 x-amz-request-id: MPD20P9P3X45BR1Q Date: Tue, 04 Jan 2022 21:02:48 GMT Last-Modified: Tue, 04 Jan 2022 20:10:26 GMT ETag: "8e26fa2b966ca8bac30678cdd6af765c" Content-Type: text/javascript Server: AmazonS3 ``` With the `Origin` header on the request it returns the `Access-Control-Allow-Origin` headers. Without it does not. I'm running my S3 bucket behind a Cloudflare cache. As you can see above, S3 returns a `Vary: Origin` header so caches know that they should respect that header when returning cached content. But... while Cloudflare [added support for Vary](https://blog.cloudflare.com/vary-for-images-serve-the-correct-images-to-the-correct-browsers/) in September 2021 they only support it for images, not for other file formats! So sadly I don't think you can use CORS for JavaScript modules in this way if you are using Cloudflare. I also tried using `"AllowedOrigins": ["*"]` in my S3 configuration, but I found that if you make a request without an `Origin` header S3 still doesn't return `Access-Control-Allow-Origin` - so under a cache that does not support Vary you run the risk of caching an asset without those headers. <p>Amazon S3 buckets that are configured to work as public websites can support CORS, allowing assets such as JavaScript modules to be loaded by JavaScript running on other domains.</p> <p>This configuration happens at the bucket level - it's not something that can be applied to individual items.</p> <p><a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html" rel="nofollow">Here's their documentation</a>. As with so many AWS things it involves hand-crafting a JSON document: the documentation for that format, with useful examples, <a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html" rel="nofollow">is here</a>.</p> <p>I opted to use the S3 web console option - find the bucket in the console interface, click the "Security" tab and you can paste in a JSON configuration.</p> <p>The configuration I tried first was this one:</p> <div class="highlight highlight-source-json"><pre>[ { <span class="pl-ent">"AllowedHeaders"</span>: [ <span class="pl-s"><span class="pl-pds">"</span>*<span class="pl-pds">"</span></span> ], <span class="pl-ent">"AllowedMethods"</span>: [ <span class="pl-s"><span class="pl-pds">"</span>GET<span class="pl-pds">"</span></span> ], <span class="pl-ent">"AllowedOrigins"</span>: [ <span class="pl-s"><span class="pl-pds">"</span>https://simonwillison.net/<span class="pl-pds">"</span></span> ], <span class="pl-ent">"ExposeHeaders"</span>: [] } ]</pre></div> <p>This should enable CORS access for GET requests from code running on my <a href="https://simonwillison.net/" rel="nofollow">https://simonwillison.net/</a> site.</p> <p>The <code>AllowedOrigins</code> key is interesting: it works by inspecting the <code>Origin</code> header on the incoming request, and returning CORS headers based on if that origin matches one of the values in the list.</p> <p>I used <code>curl -i ... -H "Origin: value"</code> to confirm that this worked:</p> <pre><code>~ % curl -i 'http://static.simonwillison.net.s3-website-us-west-1.amazonaws.com/static/2022/photoswipe/photoswipe-lightbox.esm.js' \ -H "Origin: https://simonwillison.net" | head -n 20 -x-amz-request-id: 4YY7ZBCVJ167XCR9 Date: Tue, 04 Jan 2022 21:02:44 GMT -Access-Control-Allow-Origin: * -Access-Control-Allow-Methods: GET :Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method -Last-Modified: Tue, 04 Jan 2022 20:10:26 GMT -ETag: "8e26fa2b966ca8bac30678cdd6af765c" :Content-Type: text/javascript -Server: AmazonS3 ~ % curl -i 'http://static.simonwillison.net.s3-website-us-west-1.amazonaws.com/static/2022/photoswipe/photoswipe-lightbox.esm.js' | head -n 20 x-amz-request-id: MPD20P9P3X45BR1Q Date: Tue, 04 Jan 2022 21:02:48 GMT Last-Modified: Tue, 04 Jan 2022 20:10:26 GMT ETag: "8e26fa2b966ca8bac30678cdd6af765c" Content-Type: text/javascript Server: AmazonS3 </code></pre> <p>With the <code>Origin</code> header on the request it returns the <code>Access-Control-Allow-Origin</code> headers. Without it does not.</p> <p>I'm running my S3 bucket behind a Cloudflare cache. As you can see above, S3 returns a <code>Vary: Origin</code> header so caches know that they should respect that header when returning cached content.</p> <p>But... while Cloudflare <a href="https://blog.cloudflare.com/vary-for-images-serve-the-correct-images-to-the-correct-browsers/" rel="nofollow">added support for Vary</a> in September 2021 they only support it for images, not for other file formats! So sadly I don't think you can use CORS for JavaScript modules in this way if you are using Cloudflare.</p> <p>I also tried using <code>"AllowedOrigins": ["*"]</code> in my S3 configuration, but I found that if you make a request without an <code>Origin</code> header S3 still doesn't return <code>Access-Control-Allow-Origin</code> - so under a cache that does not support Vary you run the risk of caching an asset without those headers.</p> <Binary: 73,573 bytes> 2022-01-04T15:42:13-08:00 2022-01-04T23:42:13+00:00 2022-01-04T20:33:18-08:00 2022-01-05T04:33:18+00:00 5e0c5c7fe12cdcc87bde2f7bc050a915 s3-cors
Powered by Datasette · How this site works · Code of conduct