Providers
Cloudflare R2
PUT uploads, endpoint configuration, and CORS for Cloudflare R2.
Cloudflare R2 is compatible with S3 APIs with two key differences: it requires Presigned PUT (it does not support Presigned POST), and it ignores object ACLs.
Configure upload method
Set upload: { method: "PUT" }:
import { S3Client } from "@aws-sdk/client-s3";
import { dimahS3, route } from "@dimah-s3/server";
export const awsS3 = new S3Client({
region: "auto",
endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
},
});
export const s3 = dimahS3({
client: awsS3,
bucket: process.env.R2_BUCKET!,
routes: {
avatar: route({
upload: {
method: "PUT", // Required for Cloudflare R2
fileTypes: ["image/*"],
maxFileSize: 2 * 1024 * 1024,
},
}),
},
});Bucket CORS policy
Add a CORS rule in the Cloudflare R2 dashboard for your frontend domain:
[
{
"AllowedOrigins": ["https://your-app.example"],
"AllowedMethods": ["GET", "PUT", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "Content-Type"],
"MaxAgeSeconds": 3000
}
]Frequently asked questions
Enable the public access toggle in the R2 bucket settings or connect a custom domain (e.g. cdn.example.com). Construct your image URLs directly: https://cdn.example.com/{avatarKey}.