import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; function corsHeaders(origin, allowedOrigin) { const allow = allowedOrigin || '*'; return { 'Access-Control-Allow-Origin': allow, 'Access-Control-Allow-Methods': 'GET, OPTIONS', 'Access-Control-Allow-Headers': 'Authorization', }; } function json(data, status, headers) { return new Response(JSON.stringify(data), { status: status || 200, headers: { 'Content-Type': 'application/json', ...headers }, }); } export default { async fetch(request, env) { const cors = corsHeaders(request.headers.get('Origin'), env.ALLOWED_ORIGIN); if (request.method === 'OPTIONS') { return new Response(null, { status: 204, headers: cors }); } const url = new URL(request.url); if (url.pathname !== '/presign') { return new Response('Not found', { status: 404, headers: cors }); } if (request.method !== 'GET') { return new Response('Method not allowed', { status: 405, headers: cors }); } const auth = request.headers.get('Authorization'); if (!auth || auth !== `Bearer ${env.UPLOAD_SECRET}`) { return json({ error: 'Unauthorized' }, 401, cors); } const filename = url.searchParams.get('filename'); if (!filename) { return json({ error: 'Missing filename parameter' }, 400, cors); } const safe = filename.replace(/[^a-zA-Z0-9.\-_]/g, '_'); const key = `videos/${Date.now()}-${safe}`; const client = new S3Client({ region: 'auto', endpoint: `https://${env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`, credentials: { accessKeyId: env.R2_ACCESS_KEY_ID, secretAccessKey: env.R2_SECRET_ACCESS_KEY, }, }); try { const command = new PutObjectCommand({ Bucket: env.R2_BUCKET_NAME, Key: key, }); const presignedUrl = await getSignedUrl(client, command, { expiresIn: 3600 }); return json({ url: presignedUrl, key }, 200, cors); } catch (err) { return json({ error: err.message }, 500, cors); } }, };