Backend hardening: structured logging, timeouts, memory leak fixes, compression, XSS fix
Some checks failed
Deploy to Production / Deploy to Server (push) Failing after 20s
Some checks failed
Deploy to Production / Deploy to Server (push) Failing after 20s
- Add pino structured logging with request IDs (X-Request-Id header) - Add 30s timeout to acquirePage() and renderPdf/renderUrlPdf - Add verification cache cleanup (every 15min) and rate limit cleanup (every 60s) - Read version from package.json in health endpoint - Add compression middleware - Escape currency in templates (XSS fix) - Add static asset caching (1h maxAge) - Remove deprecated docker-compose version field - Replace all console.log/error with pino logger
This commit is contained in:
parent
4833edf44c
commit
9541ae1826
20 changed files with 319 additions and 74 deletions
24
src/index.ts
24
src/index.ts
|
|
@ -1,4 +1,7 @@
|
|||
import express from "express";
|
||||
import { randomUUID } from "crypto";
|
||||
import compression from "compression";
|
||||
import logger from "./services/logger.js";
|
||||
import helmet from "helmet";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
|
@ -24,6 +27,17 @@ const PORT = parseInt(process.env.PORT || "3100", 10);
|
|||
|
||||
app.use(helmet({ crossOriginResourcePolicy: { policy: "cross-origin" } }));
|
||||
|
||||
// Request ID middleware
|
||||
app.use((req, res, next) => {
|
||||
const requestId = (req.headers["x-request-id"] as string) || randomUUID();
|
||||
(req as any).requestId = requestId;
|
||||
res.setHeader("X-Request-Id", requestId);
|
||||
next();
|
||||
});
|
||||
|
||||
// Compression
|
||||
app.use(compression());
|
||||
|
||||
// Differentiated CORS middleware
|
||||
app.use((req, res, next) => {
|
||||
const isAuthBillingRoute = req.path.startsWith('/v1/signup') ||
|
||||
|
|
@ -145,7 +159,7 @@ ${apiKey ? `
|
|||
|
||||
// Landing page
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
app.use(express.static(path.join(__dirname, "../public")));
|
||||
app.use(express.static(path.join(__dirname, "../public"), { maxAge: "1h", etag: true }));
|
||||
|
||||
// Docs page (clean URL)
|
||||
app.get("/docs", (_req, res) => {
|
||||
|
|
@ -179,11 +193,11 @@ async function start() {
|
|||
await loadUsageData();
|
||||
|
||||
await initBrowser();
|
||||
console.log(`Loaded ${getAllKeys().length} API keys`);
|
||||
app.listen(PORT, () => console.log(`DocFast API running on :${PORT}`));
|
||||
logger.info(`Loaded ${getAllKeys().length} API keys`);
|
||||
app.listen(PORT, () => logger.info(`DocFast API running on :${PORT}`));
|
||||
|
||||
const shutdown = async () => {
|
||||
console.log("Shutting down...");
|
||||
logger.info("Shutting down...");
|
||||
await closeBrowser();
|
||||
process.exit(0);
|
||||
};
|
||||
|
|
@ -192,7 +206,7 @@ async function start() {
|
|||
}
|
||||
|
||||
start().catch((err) => {
|
||||
console.error("Failed to start:", err);
|
||||
logger.error({ err }, "Failed to start");
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue