Ensure R2 CORS when using manual access keys

This commit is contained in:
thePR0M3TH3AN
2025-09-26 22:58:13 -04:00
parent 67f80787d0
commit 46c2b39aae
2 changed files with 68 additions and 3 deletions

View File

@@ -32,7 +32,11 @@ import {
attachCustomDomainAndWait,
setManagedDomain,
} from "./storage/r2-mgmt.js";
import { makeR2Client, multipartUpload } from "./storage/r2-s3.js";
import {
makeR2Client,
multipartUpload,
ensureBucketCors,
} from "./storage/r2-s3.js";
import { initQuickR2Upload } from "./r2-quick.js";
/**
@@ -1568,6 +1572,10 @@ class bitvidApp {
const accountId = (this.cloudflareSettings.accountId || "").trim();
const apiToken = (this.cloudflareSettings.apiToken || "").trim();
const zoneId = (this.cloudflareSettings.zoneId || "").trim();
const accessKeyId = (this.cloudflareSettings.accessKeyId || "").trim();
const secretAccessKey =
(this.cloudflareSettings.secretAccessKey || "").trim();
const corsOrigins = this.getCorsOrigins();
const baseDomain = this.cloudflareSettings.baseDomain || "";
if (!accountId) {
@@ -1588,7 +1596,7 @@ class bitvidApp {
accountId,
bucket: entry.bucket,
token: apiToken,
origins: this.getCorsOrigins(),
origins: corsOrigins,
});
} catch (err) {
console.warn("Failed to refresh bucket configuration:", err);
@@ -1625,6 +1633,26 @@ class bitvidApp {
lastUpdated: Date.now(),
};
if (accessKeyId && secretAccessKey && corsOrigins.length > 0) {
try {
const s3 = makeR2Client({
accountId,
accessKeyId,
secretAccessKey,
});
await ensureBucketCors({
s3,
bucket: bucketName,
origins: corsOrigins,
});
} catch (corsErr) {
console.warn(
"Failed to ensure R2 CORS rules via access keys. Configure the bucket's CORS policy manually if uploads continue to fail.",
corsErr
);
}
}
let savedEntry = entry;
if (
!entry ||
@@ -1656,7 +1684,7 @@ class bitvidApp {
accountId,
bucket: bucketName,
token: apiToken,
origins: this.getCorsOrigins(),
origins: corsOrigins,
});
} catch (err) {
console.warn("Failed to apply R2 CORS rules:", err);

View File

@@ -5,6 +5,7 @@ import {
UploadPartCommand,
CompleteMultipartUploadCommand,
AbortMultipartUploadCommand,
PutBucketCorsCommand,
} from "https://esm.sh/@aws-sdk/client-s3@3.637.0?target=es2022&bundle";
function computeCacheControl(key) {
@@ -41,6 +42,42 @@ export function makeR2Client({ accountId, accessKeyId, secretAccessKey }) {
});
}
export async function ensureBucketCors({ s3, bucket, origins }) {
if (!s3) {
throw new Error("S3 client is required to configure CORS");
}
if (!bucket) {
throw new Error("Bucket name is required to configure CORS");
}
const allowedOrigins = (origins || []).filter(Boolean);
if (allowedOrigins.length === 0) {
return;
}
const command = new PutBucketCorsCommand({
Bucket: bucket,
CORSConfiguration: {
CORSRules: [
{
AllowedHeaders: ["*"],
AllowedMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "OPTIONS"],
AllowedOrigins: allowedOrigins,
ExposeHeaders: [
"ETag",
"Content-Length",
"Content-Range",
"Accept-Ranges",
],
MaxAgeSeconds: 3600,
},
],
},
});
await s3.send(command);
}
export async function multipartUpload({
s3,
bucket,