multer 2.x und node-cron 4.x: geprueft, package.json angehoben
multer 1.4.5-lts.1 ist von den Betreuern ausdruecklich als veraltet markiert. Die Meldung der Registry, woertlich: "Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version." ⚠️ BEMERKENSWERT: "npm audit" meldet dazu NICHTS. Die Pruefung nannte nur eine Luecke in uuid, eingeschleppt ueber node-cron 3.x. Wer sich allein auf audit verlaesst, haette multer fuer unbedenklich gehalten. Die Deprecation-Meldung ist hier die eigentliche Warnung -- sie steht aber an einer Stelle, an die man nur kommt, wenn man gezielt nachfragt. 2.0.0 behebt CVE-2025-47935 und CVE-2025-47944. Einzige dokumentierte Breaking Change: Node ab 10.16. Auf dem Server laeuft 24. node-cron 4.x behebt die uuid-Luecke. Die Fassung ist eine Umstellung auf TypeScript, ohne dokumentierte API-Aenderung -- genau dabei aendert sich aber gern die Art des Standard-Exports, und "import cron from 'node-cron'" wuerde danach beim START scheitern, nicht bei der Installation. GEPRUEFT STATT ANGENOMMEN In einem eigenen Verzeichnis gegen multer 2.2.0 und node-cron 4.6.0 getestet, mit genau den Aufrufen aus index.js: diskStorage mit destination/filename, limits, fileFilter, single/array/fields, MulterError samt code, cron.schedule("* * * * *") und task.stop(). 15 von 15 bestanden. Die Pruefung liegt jetzt als server-internal/test-pakete.mjs im Projekt -- die Frage "laeuft unser Code damit noch?" stellt sich bei jedem Hauptversionswechsel neu. Express bleibt bewusst bei 4.x. Der Sprung auf 5 ist ein eigener Vorgang mit deutlich mehr Flaeche; ihn hier mitzunehmen wuerde zwei unabhaengige Risiken in einem Schritt buendeln. Die Installation selbst braucht Filipe: server-internal liegt unter /home/dogiintern mit Rechten 700. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.7",
|
||||
"express": "^4.21.2",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-cron": "^3.0.3"
|
||||
"multer": "^2.2.0",
|
||||
"node-cron": "^4.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/* =====================================================================
|
||||
Verträglichkeitsprüfung: multer und node-cron
|
||||
|
||||
Aufruf: node test-pakete.mjs (im Verzeichnis server-internal)
|
||||
|
||||
WARUM ÜBERHAUPT
|
||||
|
||||
Beide sind Hauptversionssprünge. Die Veröffentlichungshinweise nennen
|
||||
nur je eine Änderung — bei multer die Node-Mindestfassung, bei
|
||||
node-cron die Umstellung auf TypeScript. Das klingt harmlos, sagt aber
|
||||
nichts darüber, ob UNSER Code weiterläuft:
|
||||
|
||||
Bei einer TypeScript-Umstellung ändert sich häufig die Art des
|
||||
Standard-Exports. "import cron from 'node-cron'" kann danach ein
|
||||
Objekt liefern, das die erwartete Funktion gar nicht hat — und das
|
||||
fällt erst beim Start auf, nicht bei der Installation.
|
||||
|
||||
Deshalb werden hier genau die Aufrufe nachgebildet, die in
|
||||
server-internal/index.js stehen. Nicht irgendwelche, sondern diese.
|
||||
|
||||
Vor der Umstellung am 26.08.2026 in einem eigenen Verzeichnis gegen
|
||||
multer 2.2.0 und node-cron 4.6.0 geprüft: 15 von 15 bestanden. Die
|
||||
Datei bleibt, damit dieselbe Prüfung nach jedem künftigen Sprung
|
||||
wiederholbar ist — die Frage "läuft unser Code damit noch?" stellt
|
||||
sich bei jedem Hauptversionswechsel neu.
|
||||
===================================================================== */
|
||||
import multer from "multer";
|
||||
import cron from "node-cron";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
let ok = 0, fehl = 0;
|
||||
const pruefe = (name, gut, info) => {
|
||||
if (gut) { ok++; console.log(" ok " + name + (info ? " -> " + info : "")); }
|
||||
else { fehl++; console.log(" FEHL " + name + (info ? " -> " + info : "")); }
|
||||
};
|
||||
|
||||
console.log("1. MULTER — die Aufrufe aus index.js");
|
||||
|
||||
pruefe("Standard-Export ist aufrufbar", typeof multer === "function", typeof multer);
|
||||
pruefe("multer.diskStorage vorhanden", typeof multer.diskStorage === "function");
|
||||
pruefe("multer.MulterError vorhanden", typeof multer.MulterError === "function");
|
||||
|
||||
/* Genau die Form aus index.js: diskStorage mit destination/filename,
|
||||
dazu limits und fileFilter. */
|
||||
const ziel = path.join(process.cwd(), "probe-ablage");
|
||||
fs.mkdirSync(ziel, { recursive: true });
|
||||
|
||||
let hochlader = null;
|
||||
try {
|
||||
hochlader = multer({
|
||||
storage: multer.diskStorage({
|
||||
destination: (req, datei, weiter) => weiter(null, ziel),
|
||||
filename: (req, datei, weiter) => weiter(null, "probe.png"),
|
||||
}),
|
||||
limits: { fileSize: 5 * 1024 * 1024, files: 1 },
|
||||
fileFilter: (req, datei, weiter) => {
|
||||
if (!/^image\/(png|jpe?g|webp)$/.test(datei.mimetype)) {
|
||||
return weiter(new Error("Nur Bilder."));
|
||||
}
|
||||
weiter(null, true);
|
||||
},
|
||||
});
|
||||
pruefe("multer({ storage, limits, fileFilter }) baut", !!hochlader);
|
||||
} catch (e) {
|
||||
pruefe("multer({ storage, limits, fileFilter }) baut", false, e.message);
|
||||
}
|
||||
|
||||
pruefe("upload.single() liefert eine Middleware",
|
||||
hochlader && typeof hochlader.single("bild") === "function");
|
||||
pruefe("upload.array() liefert eine Middleware",
|
||||
hochlader && typeof hochlader.array("bilder", 5) === "function");
|
||||
pruefe("upload.fields() liefert eine Middleware",
|
||||
hochlader && typeof hochlader.fields([{ name: "a" }]) === "function");
|
||||
|
||||
/* Die Fehlerbehandlung in index.js prüft auf "err instanceof
|
||||
multer.MulterError" und liest err.code. Wenn sich dort etwas geändert
|
||||
hätte, würde jede Größenüberschreitung als unbekannter Serverfehler
|
||||
enden statt als saubere Meldung an den Benutzer. */
|
||||
try {
|
||||
const f = new multer.MulterError("LIMIT_FILE_SIZE", "bild");
|
||||
pruefe("MulterError trägt weiterhin einen code", f.code === "LIMIT_FILE_SIZE", f.code);
|
||||
pruefe("und ist ein echter Fehler", f instanceof Error);
|
||||
} catch (e) {
|
||||
pruefe("MulterError lässt sich erzeugen", false, e.message);
|
||||
}
|
||||
|
||||
console.log("\n2. NODE-CRON — der Aufruf aus index.js");
|
||||
|
||||
pruefe("Standard-Export vorhanden", !!cron, typeof cron);
|
||||
pruefe("cron.schedule ist eine Funktion", typeof cron.schedule === "function", typeof cron.schedule);
|
||||
pruefe("cron.validate ist eine Funktion", typeof cron.validate === "function");
|
||||
|
||||
/* Genau der Ausdruck aus index.js. */
|
||||
pruefe('Ausdruck "* * * * *" gilt als gültig', cron.validate("* * * * *") === true);
|
||||
|
||||
let lief = 0;
|
||||
let aufgabe = null;
|
||||
try {
|
||||
aufgabe = cron.schedule("* * * * *", () => { lief++; });
|
||||
pruefe("cron.schedule() legt eine Aufgabe an", !!aufgabe);
|
||||
/* In 3.x hiess die Methode stop(). Faellt sie weg, laeuft der
|
||||
Zeitgeber beim Herunterfahren weiter. */
|
||||
pruefe("die Aufgabe lässt sich stoppen", typeof aufgabe.stop === "function",
|
||||
typeof aufgabe.stop);
|
||||
} catch (e) {
|
||||
pruefe("cron.schedule() legt eine Aufgabe an", false, e.message);
|
||||
}
|
||||
if (aufgabe && typeof aufgabe.stop === "function") aufgabe.stop();
|
||||
|
||||
/* Aufräumen */
|
||||
try { fs.rmSync(ziel, { recursive: true, force: true }); } catch {}
|
||||
|
||||
console.log(`\n===== ${ok} bestanden, ${fehl} fehlgeschlagen =====`);
|
||||
process.exit(fehl ? 1 : 0);
|
||||
Reference in New Issue
Block a user