feat: validate and persist per-file quality in POST /api/jobs

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 23:30:23 +02:00
co-authored by Claude Sonnet 5
parent d827f55e46
commit 4cb9d76176
2 changed files with 89 additions and 0 deletions
+34
View File
@@ -13,6 +13,14 @@ import { deleteIfExists } from './storage.js';
import { createJob, getJobByUuid } from './jobs/jobRepository.js';
import { outputPath } from './storage.js';
function isValidQuality(targetFormat, quality) {
if (quality === null || quality === undefined) return true;
if (!Number.isInteger(quality)) return false;
if (targetFormat === 'gif') return false;
if (targetFormat === 'png') return quality >= 0 && quality <= 9;
return quality >= 1 && quality <= 100;
}
let convertersRegistered = false;
function registerAllConverters() {
@@ -73,6 +81,21 @@ export function createApp(config, pool) {
return res.status(400).json({ error: 'targetFormats must have one entry per uploaded file' });
}
let qualities;
try {
qualities = JSON.parse(req.body.qualities ?? '[]');
} catch {
return res.status(400).json({ error: 'qualities must be a JSON array' });
}
if (!Array.isArray(qualities)) {
return res.status(400).json({ error: 'qualities must be a JSON array' });
}
if (qualities.length > 0 && qualities.length !== req.files.length) {
return res.status(400).json({ error: 'qualities must have one entry per uploaded file, or be omitted' });
}
const results = [];
for (let i = 0; i < req.files.length; i += 1) {
const file = req.files[i];
@@ -97,6 +120,16 @@ export function createApp(config, pool) {
continue;
}
const requestedQuality = qualities[i] ?? null;
if (!isValidQuality(targetFormat, requestedQuality)) {
await deleteIfExists(file.path);
results.push({
file: file.originalname,
error: `Invalid quality for target format ${targetFormat}`,
});
continue;
}
const expiresAt = new Date(Date.now() + config.retentionHours * 3600 * 1000);
await createJob(pool, {
uuid,
@@ -108,6 +141,7 @@ export function createApp(config, pool) {
inputMimeType: mime,
inputSizeBytes: file.size,
expiresAt,
quality: requestedQuality,
});
results.push({ file: file.originalname, id: uuid, status: 'pending' });