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]>
116 lines
4.7 KiB
JavaScript
116 lines
4.7 KiB
JavaScript
/* =====================================================================
|
|
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);
|