CORS issue with R2 Presigned URL

I am trying to use R2 presigned URL on browser. The request fails due to CORS.

I have faced similar issue on S3 and I know the solution: setting the CORSRule

According to R2 docs, changing CORSRule on dashboard is not supported yet. It is only available via S3 API.

So I did this.

    r2.putBucketCors(
      {
        Bucket: 'game-resources',
        CORSConfiguration: {
          CORSRules: [
            {
              AllowedMethods: ['PUT'],
              AllowedOrigins: ['*'],
              AllowedHeaders: ['*'],
            },
          ],
        },
      },
      (err, data) => {
        console.log(err, data)
      }
    )

and it returns correct CORS Rule when I call this

    r2.getBucketCors({ Bucket: 'game-resources' }, (err, data) => {
      console.log(err, JSON.stringify(data))
    })
{"CORSRules":[{"AllowedHeaders":["*"],"AllowedMethods":["PUT"],"AllowedOrigins":["http://localhost:3000"],"ExposeHeaders":[]}]}

But there’s still 403 CORS error when I try to use it on browser.

I tried using curl for OPTION request to check what the response throws.

  -X 'OPTIONS' \
  -H 'Accept: */*' \
  -H 'Accept-Language: ko,en;q=0.9,ko-KR;q=0.8,en-US;q=0.7' \
  -H 'Access-Control-Request-Headers: content-type' \
  -H 'Access-Control-Request-Method: PUT' \
  -H 'Connection: keep-alive' \
  -H 'Origin: http://localhost:3000' \
  -H 'Referer: http://localhost:3000/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36' \
  --compressed
<?xml version="1.0" encoding="UTF-8"?><Error><Code>Unauthorized</Code><Message>CORS not configured for this bucket</Message></Error>

It says CORS not configured for this bucket.

Hey guys I solved this issue.
I found solution from Cloudflare discord.

https://discord.com/channels/595317990191398933/1026190531056902184/1028195445580771379

https://gist.github.com/jeremywall/c87a7bcf423a6dab780d0fb0054c7e6d

If you are using Node.js do this:

r2.putBucketCors(
      {
        Bucket: 'game-resources',
        CORSConfiguration: {
          CORSRules: [
            {
              AllowedMethods: ['PUT'],
              AllowedOrigins: ['*'],
              AllowedHeaders: ['content-type'],
            },
          ],
        },
      },
      (err, data) => {
        console.log(err, data)
      }
    )

Then, it will work.

5 Likes

Thank you for sharing this. Spent hours trying to figure out why my S3 CORS rule set wasn’t working on R2. Turns out, R2 doesn’t support a wildcard AllowedHeaders. So unintuitive.

2 Likes

If you are trying to use the aws-sdk js v3, here is a reference: https://ehtesham.dev/blog/how-to-fix-cors-error-while-uploading-files-on-cloudflare-r2-using-presigned-urls?utm_source=cf-community

1 Like

Mamma Mia! AllowedHeaders: ['content-type'] works. :grinning: