4b96e1a6b0
- env.js: '…CHANGE-ME'-Platzhalter aus .env.example zählen als NICHT gesetzt. Vorher galt sk_test_CHANGE-ME als echter Stripe-Key → echter API-Call mit ungültigem Key → 401 → unhandledRejection → Server-Crash. - billing.js: /checkout in try/catch → 502 statt Empty-Reply/Crash. - index.js: globaler Express-Error-Handler + unhandledRejection-Guard, damit ein einzelner async-Fehler nie den ganzen Prozess killt. E2E verifiziert (Mock): register→checkout→instance, idempotent (1 sub/1 inst), 401 bei falschem PW, Server lebt nach allen Requests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
46 lines
1.9 KiB
JavaScript
46 lines
1.9 KiB
JavaScript
// RAPPORT-HOST Backend-Entry.
|
|
import express from "express";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { env } from "./env.js";
|
|
import { authRouter } from "./routes/auth.js";
|
|
import { billingRouter } from "./routes/billing.js";
|
|
import { accountRouter } from "./routes/account.js";
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const app = express();
|
|
|
|
// WICHTIG: Der Stripe-Webhook braucht den ROHEN Body für die Signaturprüfung.
|
|
// express.raw greift nur für diese Route und setzt req._body, sodass das danach
|
|
// registrierte express.json() den Webhook-Body NICHT erneut parst.
|
|
app.use("/api/billing/webhook", express.raw({ type: "application/json" }));
|
|
app.use(express.json());
|
|
|
|
app.get("/api/health", (_req, res) => res.json({ ok: true, service: "rapport-host" }));
|
|
app.use("/api/auth", authRouter);
|
|
app.use("/api/billing", billingRouter);
|
|
app.use("/api/account", accountRouter);
|
|
|
|
// In Produktion liefert dasselbe Backend das gebaute Frontend aus (dist/).
|
|
const dist = path.resolve(__dirname, "..", "dist");
|
|
app.use(express.static(dist));
|
|
app.get("*", (req, res, next) => {
|
|
if (req.path.startsWith("/api/")) return next();
|
|
res.sendFile(path.join(dist, "index.html"), (err) => err && next());
|
|
});
|
|
|
|
// Express-Fehlerhandler: fängt synchron geworfene Fehler aus Routen → 500
|
|
// statt stiller Empty-Reply.
|
|
app.use((err, _req, res, _next) => {
|
|
console.error("Unbehandelter Routen-Fehler:", err);
|
|
if (!res.headersSent) res.status(500).json({ error: "Interner Fehler." });
|
|
});
|
|
|
|
// Letzte Verteidigungslinie: ein einzelner async-Fehler darf den Prozess nicht
|
|
// killen (im Dev-Test sonst "connection refused" für alle Folge-Requests).
|
|
process.on("unhandledRejection", (reason) => console.error("unhandledRejection:", reason));
|
|
|
|
app.listen(env.port, () => {
|
|
console.log(`RAPPORT-HOST API läuft auf :${env.port} (Base: ${env.publicBaseUrl})`);
|
|
});
|