Files
dyzulk.github.io/workers/r2-presign.js
2026-01-16 17:04:24 +07:00

86 lines
2.4 KiB
JavaScript

/**
* Cloudflare Worker for Presigned R2 URLs
*
* SETUP INSTRUCTIONS:
* 1. Create a new Worker in Cloudflare Dashboard.
* 2. Copy this code into the Worker editor.
* 3. Go to Settings -> Variables and add:
* - R2_BUCKET_NAME
* - R2_ACCOUNT_ID
* - R2_ACCESS_KEY_ID
* - R2_SECRET_ACCESS_KEY
* - ALLOWED_ORIGIN (e.g., https://dyzulk.github.io, or * for dev)
* 4. Deploy!
*/
import { AwsClient } from 'aws4fetch'
export default {
async fetch(request, env) {
// 1. Handle CORS Preflight
if (request.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": env.ALLOWED_ORIGIN || "*",
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
},
});
}
if (request.method !== "POST") {
return new Response("Method not allowed", { status: 405 });
}
try {
// 2. Auth Check (Simple)
// For production, verify Supabase JWT token here if needed.
// For now, we trust the Client if it knows the endpoint (obscurity) or checking Origin.
const body = await request.json();
const { fileName, fileType } = body;
if (!fileName || !fileType) {
return new Response("Missing fileName or fileType", { status: 400 });
}
// 3. Initialize AWS Client (R2 S3-Compatible)
const r2 = new AwsClient({
accessKeyId: env.R2_ACCESS_KEY_ID,
secretAccessKey: env.R2_SECRET_ACCESS_KEY,
service: 's3',
region: 'auto',
});
// 4. Generate Presigned URL
const url = new URL(
`https://${env.R2_BUCKET_NAME}.${env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com/${fileName}`
);
// Sign the request
// We sign a PUT request for the specific file
const signed = await r2.sign(
new Request(url, {
method: 'PUT',
headers: {
'Content-Type': fileType
}
}),
{
aws: { signQuery: true }, // Create presigned URL with query params
}
);
return new Response(JSON.stringify({ url: signed.url }), {
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": env.ALLOWED_ORIGIN || "*",
},
});
} catch (e) {
return new Response(JSON.stringify({ error: e.message }), { status: 500 });
}
},
};