mirror of
https://github.com/ZSCGR/CloudFlare-ImgBed.git
synced 2026-08-13 04:03:42 +08:00
fix: harden batch delete request handling
This commit is contained in:
@@ -12,7 +12,11 @@ const corsHeaders = {
|
||||
'Access-Control-Max-Age': '86400',
|
||||
};
|
||||
|
||||
export async function onRequestPost(context) {
|
||||
export async function onRequest(context) {
|
||||
if (context.request.method !== 'POST') {
|
||||
return jsonResponse({ success: false, error: 'Method not allowed' }, 405);
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = await context.request.json();
|
||||
const fileIds = normalizeBatchFileIds(payload?.fileIds, MAX_BATCH_SIZE);
|
||||
@@ -21,9 +25,13 @@ export async function onRequestPost(context) {
|
||||
}
|
||||
const url = new URL(context.request.url);
|
||||
const results = await mapConcurrent(fileIds, DELETE_CONCURRENCY, async (fileId) => {
|
||||
const cdnUrl = `${url.origin}/file/${fileId.split('/').map(encodeURIComponent).join('/')}`;
|
||||
const success = await deleteFile(context.env, fileId, cdnUrl, url);
|
||||
return { fileId, success, error: success ? '' : 'Delete file failed' };
|
||||
try {
|
||||
const cdnUrl = `${url.origin}/file/${fileId.split('/').map(encodeURIComponent).join('/')}`;
|
||||
const success = await deleteFile(context.env, fileId, cdnUrl, url);
|
||||
return { fileId, success, error: success ? '' : 'Delete file failed' };
|
||||
} catch (err) {
|
||||
return { fileId, success: false, error: String(err?.message || err) };
|
||||
}
|
||||
});
|
||||
|
||||
const deleted = results.filter((item) => item.success).map((item) => item.fileId);
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
export function normalizeBatchFileIds(values, maxBatchSize) {
|
||||
if (!Array.isArray(values)) return [];
|
||||
const normalized = [...new Set(values
|
||||
.map((value) => String(value || '').trim().replace(/^\/+|\/+$/g, ''))
|
||||
.filter(Boolean))];
|
||||
const normalized = [];
|
||||
const seen = new Set();
|
||||
|
||||
for (const value of values) {
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error('fileIds must be an array of strings');
|
||||
}
|
||||
|
||||
const fileId = value.trim().replace(/^\/+|\/+$/g, '');
|
||||
if (fileId && !seen.has(fileId)) {
|
||||
seen.add(fileId);
|
||||
normalized.push(fileId);
|
||||
}
|
||||
}
|
||||
|
||||
if (normalized.length > maxBatchSize) {
|
||||
throw new Error(`A maximum of ${maxBatchSize} files can be deleted at once`);
|
||||
}
|
||||
@@ -11,8 +23,14 @@ export function normalizeBatchFileIds(values, maxBatchSize) {
|
||||
|
||||
export async function mapConcurrent(values, concurrency, operation) {
|
||||
const results = new Array(values.length);
|
||||
if (values.length === 0) return results;
|
||||
|
||||
const workerCount = Math.min(
|
||||
Math.max(1, Math.floor(Number(concurrency) || 1)),
|
||||
values.length
|
||||
);
|
||||
let nextIndex = 0;
|
||||
const workers = Array.from({ length: Math.min(concurrency, values.length) }, async () => {
|
||||
const workers = Array.from({ length: workerCount }, async () => {
|
||||
while (nextIndex < values.length) {
|
||||
const index = nextIndex++;
|
||||
results[index] = await operation(values[index]);
|
||||
|
||||
Reference in New Issue
Block a user