Sicherheits-, Stabilitaets- und Domainkorrekturen nach vollstaendiger Pruefung
Build & Deploy / deploy (push) Waiting to run

- Absturzsicherheit: Express 4 faengt Fehler aus async-Handlern nicht ab, eine
  einzige fehlerhafte Anfrage konnte den ganzen Shop beenden - besonders heikel
  bei capture-order, wo das direkt nach der PayPal-Abbuchung passieren wuerde.
  Neu: lib/async-wrap.js um alle Handler, zentraler Fehler-Handler in index.js,
  .catch(next) in der Zugangsschranke, unhandledRejection/uncaughtException-Netz.
- Fehlerhaftes JSON lieferte bisher Express' HTML-Fehlerseite mit komplettem
  Stacktrace und Serverpfaden (weil NODE_ENV nicht gesetzt war). Jetzt saubere
  JSON-Antwort, NODE_ENV=production in .env.example ergaenzt.
- Sicherheits-Header und x-powered-by wie bei der DogFather-Seite.
- Falsche Domain .de statt .com korrigiert: astro.config.mjs (betraf alle
  Canonical-URLs und die komplette Sitemap), robots.txt, Layout.astro sowie den
  Verwaltungs-Link in jeder Bestellbenachrichtigung (war ein toter Link).
- Fehlende Uebersetzung nav.cart in EN/CH/FR ergaenzt: das Warenkorb-Symbol hatte
  in drei von vier Sprachen keinen Namen fuer Screenreader.
This commit is contained in:
qcigano
2026-08-05 22:33:49 +02:00
parent 654f4455cc
commit ab3a5da892
14 changed files with 94 additions and 28 deletions
+39
View File
@@ -35,6 +35,19 @@ const app = express();
// Läuft hinter Caddy (Reverse Proxy) — nötig, damit req.protocol/req.get("host") und
// "secure"-Cookies korrekt funktionieren, statt anzunehmen, die Verbindung sei unverschlüsselt.
app.set("trust proxy", 1);
app.disable("x-powered-by"); // verrät sonst unnötig den eingesetzten Technik-Stack
/* Sicherheits-Header, ergänzt 05.08.2026 (bei Cloudflare Pages kamen die teils von der Plattform;
auf dem eigenen Server muss der Server sie selbst setzen). `payment=(self)` bleibt erlaubt,
damit die PayPal-Zahlung im eigenen Fenster weiter funktioniert. */
app.use((req, res, next) => {
res.setHeader("X-Content-Type-Options", "nosniff");
res.setHeader("X-Frame-Options", "SAMEORIGIN");
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
res.setHeader("Permissions-Policy", "geolocation=(), microphone=(), camera=(), payment=(self)");
res.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
next();
});
app.use(cookieParser());
app.use(express.json({ limit: "2mb" }));
@@ -63,6 +76,32 @@ app.use((req, res) => {
});
});
/* ---------- Fehler-Handler (muss NACH allen Routen stehen), ergänzt 05.08.2026 ----------
Express 4 fängt Fehler aus async-Handlern nicht selbst ab. Ohne diesen Handler landete kaputtes
JSON in Express' Standard-Fehlerseite — inklusive komplettem Stacktrace mit Serverpfaden, solange
NODE_ENV nicht auf "production" steht. Jetzt kommt in jedem Fall eine saubere JSON-Antwort. */
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
if (err?.type === "entity.parse.failed") {
return res.status(400).json({ ok: false, error: "Ungültige Anfrage." });
}
if (err?.type === "entity.too.large") {
return res.status(413).json({ ok: false, error: "Die Anfrage ist zu groß." });
}
console.error(`[fehler] ${req.method} ${req.originalUrl}:`, err?.stack || err);
if (res.headersSent) return;
if (req.path.startsWith("/api/")) {
return res.status(500).json({ ok: false, error: "Interner Fehler." });
}
return res.status(500).send("Es ist ein Fehler aufgetreten. Bitte später erneut versuchen.");
});
/* Letztes Netz: Ein unbehandelter Fehler darf den Shop nicht offline nehmen — besonders wichtig
direkt nach einer PayPal-Abbuchung, wo ein Absturz die Kundin ohne Rückmeldung zurücklassen
würde, obwohl das Geld bereits eingezogen ist. */
process.on("unhandledRejection", (grund) => console.error("[unhandledRejection]", grund));
process.on("uncaughtException", (fehler) => console.error("[uncaughtException]", fehler?.stack || fehler));
app.listen(PORT, "127.0.0.1", () => {
console.log(`Van's DIY & Bastelbedarf Server läuft auf http://127.0.0.1:${PORT}`);
});