Setting up Pre-Signed urls with custom domain name and CDN in PHP

Been seeing a few questions surrounding this issue and it seems like the tutorials for this aren’t very clear.

I followed the guide here

So I have a few questions since this is not working:

  1. For a CDN, which endpoint do I use exactly? I see 4 possible endpoints and the language is confusing as to which one to use:
  1. When I use the PHP code example, I get back the wrong path. It adds the bucket name into the path. For example:
$cmd = $client->getCommand('GetObject', [
    'Bucket' => 'example-space-name',
    'Key'    => 'path/to/file.ext'

$request = $client->createPresignedRequest($cmd, '+5 minutes');
$presignedUrl = (string) $request->getUri();

echo $presignedUrl."\n";


That path is incorrect I believe. It should be:

When I was testing with the endpoint values, I was getting a mix of XML error responses. Either AccessDenied or SignatureMismatch.

One last thing, I noticed this text in regards to using a CDN:

You can use presigned URLs with the Spaces CDN. To do so, configure your SDK or S3 tool to use the non-CDN endpoint, generate a presigned URL for a GetObject request, then modify the hostname in the URL to be the CDN hostname (<space-name>.<region>, unless the Space uses a custom hostname).

I don’t see a code example for this case in PHP or any of the other languages.

Where am I going wrong here?

Submit an answer

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!

Sign In or Sign Up to Answer

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.

I’ll just chime in here that our team got this working using this pre-signer AWS S3 package

And code like:

    const bucketParams: PutObjectCommandInput = {
      Bucket: this.digitalOceanSpace,
      Key: generateFilePath(metadata),

    return await getSignedUrl(this.client, new GetObjectCommand(bucketParams), {
      expiresIn: 15 * 60,

To generate the pre-signed download URL with a URL like

Then were able to swap the URL domain (just using a RegEx) to

And it worked just fine. Our custom CDN domain was set up using an external DNS provider, and the certs created using certbot and added manually via the DO UI.

Hope this helps anyone else!

I have the same issue. I can’t just substitute the URL like they say in the documentation.

I got SignatureMismatch

I’m struggling with the same issue here. Does anyone from DO have any advice?