Generate signed URL for R2 from Cloudflare worker

1.7k views Asked by At

I am trying to replicate the result from this guide: https://developers.cloudflare.com/r2/data-access/s3-api/presigned-urls/ However, with the exact same code, the signedUrl variable return empty object({}). If anyone has any insight would be much appreciated! According to my understanding and as written in the docs, I don't have to pass any accessKeyId or secretAccessKey. However, the s3 url that I got from my cloudflare dashboard is : https://<ACCOUNT ID>.r2.cloudflarestorage.com/<DROPBOX BUCKET>, which is different from the docs.

const r2 = new AwsClient({
  accessKeyId: "",
  secretAccessKey: "",
  service: "s3",
  region: "auto",
});

app.get("/getUploadUrl", async (c) => {
  const timeOut = +c.req.queries("timeOut") ?? 60 * 5;
  const fileName = c.req.queries("fileName") ?? crypto.randomUUID();
  const bucketName = c.req.header("bucket");
  const bucketUrl = bucketNameToUrl[bucketName];
  console.log("fileName", fileName);
  const signedUrl = await r2.sign(
    new Request(`${bucketUrl}/${fileName}`, {
      method: "PUT",
    }),
    {
      aws: { signQuery: true },
      headers: {
        "X-Amz-Expires": timeOut.toString(),
      },
    }
  );
  return c.json(signedUrl);
});
2

There are 2 answers

0
Alejandra On

You can also use the URL format: https://<bucket_name>.<account_id>.r2.cloudflarestorage.com both the slash at the end and this version should work.

The Access Key and Secret Access Key need to be generated with the button on the right of the R2 console labelled "R2 API Keys". There's also a Discord server where you can get help and learn a lot about R2, and Cloudflare in general

0
McNiel Viray On

try this,

import { S3Client, PutObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectCommand,CopyObjectCommand  } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

function configureS3client (env: Env) {
    return new S3Client({
        region: "auto",
        endpoint: `https://${env.ACCOUNT_ID}.r2.cloudflarestorage.com`,
        credentials: {
            accessKeyId: env.ACCESS_KEY_ID,
            secretAccessKey: env.SECRET_ACCESS_KEY,
        },
    });
}

export async function getPresignedURL(env: Env, bucket: string, key: string) {
    const S3 = configureS3client(env);
  
    return await getSignedUrl(
        S3,
        new PutObjectCommand({ Bucket: bucket, Key: key }),
        { expiresIn: 3600 }
    );
}