Report this

What is the reason for this report?

CORS issue with presigned URL once I add ACL: 'PublicRead'

Posted on July 28, 2022

Hello,

So I’m trying to upload to Spaces using the AWS s3 presigned URL SDK, but I’m getting a CORS error whenever I set the ACL to public read.

// generates URL without "x-amz-acl=public-read"
// does not throw CORS error, but uploads a private file that blocks public access

const s3Params = {
    Bucket: process.env.UploadBucket,
    Key,
    Expires: URL_EXPIRATION_SECONDS,
    ContentType: decodeURIComponent(mimeType)
  }
  const uploadURL = await s3.getSignedUrlPromise('putObject', s3Params)


// generates URL with "x-amz-acl=public-read" query string parameter
// throws CORS error when I try to PUT an object there

const s3Params = {
    Bucket: process.env.UploadBucket,
    Key,
    Expires: URL_EXPIRATION_SECONDS,
    ContentType: decodeURIComponent(mimeType),
    ACL: 'public-read'
  }
  const uploadURL = await s3.getSignedUrlPromise('putObject', s3Params)

In my spaces config, I have Allowed Headers set to “*”, so I’m not sure what is causing the CORS error. Any ideas?



This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Hi there,

From what I have seen, this is expected behavior with DigitalOcean Spaces and presigned URLs. When you add ACL: 'public-read', the presigned URL typically expects the x-amz-acl header to be part of the request. From the browser side, that usually turns the upload into a non-simple CORS request, which then triggers a preflight OPTIONS check.

Even if your CORS config allows *, in practice you may still need to explicitly allow x-amz-acl in the Spaces CORS settings and make sure PUT and OPTIONS are listed as allowed methods. Otherwise the browser can block the upload before it reaches Spaces.

Two approaches that often work:

You can keep using public-read, but update your Spaces CORS config to explicitly include x-amz-acl in Allowed Headers.

Or you can upload the object as private (no ACL in the presigned URL) and then make it public afterward from the server side or via a public bucket. That tends to avoid most CORS edge cases in the browser.

So while there could be a few moving parts here, depending on the client and SDK, the x-amz-acl header requirement is usually the main trigger for this kind of CORS error.

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Start building today

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.