harpy
harpy

Reputation: 11

Generate signed URL for R2 from Cloudflare worker

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);
});

Upvotes: 1

Views: 3891

Answers (2)

McNiel Viray
McNiel Viray

Reputation: 101

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 }
    );
}

Upvotes: 1

Alejandra
Alejandra

Reputation: 11

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

Upvotes: 1

Related Questions