Given the following configuration
resource "aws_s3_bucket" "content" {
bucket = "content"
}
resource "aws_s3_bucket_cors_configuration" "content" {
bucket = aws_s3_bucket.content.bucket
cors_rule {
allowed_headers = ["*"]
allowed_methods = [
"HEAD",
"PUT",
"DELETE",
"POST",
]
allowed_origins = [
"http://localhost:5713"
]
expose_headers = [
"Access-Control-Allow-Origin",
"ETag"
]
max_age_seconds = 5000
}
}
And a route like so
import { GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import { s3Client } from '../lib/awsClient';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
type Method = 'PUT' | 'GET';
export const generatePresignedUrl = async (method: Method, path: string) => {
const type = method === 'PUT' ? PutObjectCommand : GetObjectCommand;
const command = new type({
Bucket: 'content',
Key: path,
});
const url = await getSignedUrl(s3Client, command, { expiresIn: 3600 });
return url;
};
If I make a request to the returned URL (I’ve mangled it in the response below on purpose) from a Chrome window the console reports
Access to fetch at 'http://127.0.0.1:4566/content/applications/1/file?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIARF52ELDSBKKXS%2F20230424%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20230424T200913Z&X-Amz-Expires=3600&X-Amz-Signature=ecea4238399f343a7cb0b22d52c1b96641a5c0c38a8263f9388276306dd2a&X-Amz-SignedHeaders=host&x-id=PutObject' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Using * isn’t an option as the fetch request later is done with credentials: include
which isn’t supported by *
awslocal s3api get-bucket-cors --bucket content
reports
{
"CORSRules": [
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"POST",
"HEAD",
"DELETE",
"PUT"
],
"AllowedOrigins": [
"http://localhost:5713"
],
"ExposeHeaders": [
"ETag",
"Access-Control-Allow-Origin"
],
"MaxAgeSeconds": 5000
}
]
}
Which looks correct.
What exactly is blocking me? I’ve read some questionable material about Chrome not supporting localhost CORS requests but this behavior also happens in Safari.
I found this page and followed the steps including adding more methods and the localstack app origin: S3 | Docs
The output in the console is still
content:1 Access to XMLHttpRequest at 'https://localhost.localstack.cloud:4566/content?list-type=2&max-keys=1000&prefix=' from origin 'https://app.localstack.cloud' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.