webupdate
This commit is contained in:
@@ -138,34 +138,38 @@ app.get("/index", (req, res) => {
|
||||
app.use(
|
||||
express.static(path.join(baseDir, "public"), {
|
||||
index: false,
|
||||
maxAge: "30d", // Cache static files for 30 days
|
||||
etag: true,
|
||||
lastModified: true,
|
||||
setHeaders: (res, filepath) => {
|
||||
// Aggressive caching for versioned files
|
||||
if (
|
||||
filepath.includes("?v=") ||
|
||||
filepath.match(/\.(\w+)\.[a-f0-9]{8,}\./)
|
||||
) {
|
||||
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
||||
// Short cache for CSS/JS files (use cache busting for updates)
|
||||
if (filepath.endsWith(".css") || filepath.endsWith(".js")) {
|
||||
res.setHeader("Cache-Control", "public, max-age=300"); // 5 minutes
|
||||
} else if (filepath.endsWith(".html")) {
|
||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
} else {
|
||||
res.setHeader("Cache-Control", "public, max-age=86400"); // 1 day default
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
app.use(
|
||||
"/assets",
|
||||
express.static(path.join(baseDir, "assets"), {
|
||||
maxAge: "365d", // Cache assets for 1 year
|
||||
express.static(path.join(baseDir, "public", "assets"), {
|
||||
etag: true,
|
||||
lastModified: true,
|
||||
immutable: true,
|
||||
setHeaders: (res, filepath) => {
|
||||
// Add immutable for all asset files
|
||||
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
||||
|
||||
// Add resource hints for fonts
|
||||
if (filepath.endsWith(".woff2") || filepath.endsWith(".woff")) {
|
||||
// Very short cache for CSS/JS to see changes quickly (with cache busting)
|
||||
if (filepath.endsWith(".css") || filepath.endsWith(".js")) {
|
||||
res.setHeader("Cache-Control", "public, max-age=300"); // 5 minutes
|
||||
} else if (
|
||||
filepath.endsWith(".woff2") ||
|
||||
filepath.endsWith(".woff") ||
|
||||
filepath.endsWith(".ttf")
|
||||
) {
|
||||
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
|
||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
||||
} else {
|
||||
res.setHeader("Cache-Control", "public, max-age=86400"); // 1 day for images
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -183,6 +187,22 @@ app.use(
|
||||
);
|
||||
|
||||
// Session middleware
|
||||
// SECURITY: Ensure SESSION_SECRET is set - fail fast if missing
|
||||
if (
|
||||
!process.env.SESSION_SECRET ||
|
||||
process.env.SESSION_SECRET === "change-this-secret"
|
||||
) {
|
||||
if (!isDevelopment()) {
|
||||
logger.error(
|
||||
"CRITICAL: SESSION_SECRET environment variable must be set in production!"
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
logger.warn(
|
||||
"WARNING: Using insecure session secret. Set SESSION_SECRET in production!"
|
||||
);
|
||||
}
|
||||
|
||||
app.use(
|
||||
session({
|
||||
store: new pgSession({
|
||||
@@ -190,7 +210,9 @@ app.use(
|
||||
tableName: "session",
|
||||
createTableIfMissing: true,
|
||||
}),
|
||||
secret: process.env.SESSION_SECRET || "change-this-secret",
|
||||
secret:
|
||||
process.env.SESSION_SECRET ||
|
||||
(isDevelopment() ? "dev-secret-change-in-production" : ""),
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
cookie: {
|
||||
@@ -227,6 +249,8 @@ const adminRoutes = require("./routes/admin");
|
||||
const publicRoutes = require("./routes/public");
|
||||
const usersRoutes = require("./routes/users");
|
||||
const uploadRoutes = require("./routes/upload");
|
||||
const customerAuthRoutes = require("./routes/customer-auth");
|
||||
const customerCartRoutes = require("./routes/customer-cart");
|
||||
|
||||
// Admin redirect - handle /admin to redirect to login (must be before static files)
|
||||
app.get("/admin", (req, res) => {
|
||||
@@ -259,6 +283,14 @@ app.use((req, res, next) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle dynamic product pages: /product/:slug -> product.html
|
||||
if (req.path.startsWith("/product/")) {
|
||||
const productHtmlPath = path.join(baseDir, "public", "product.html");
|
||||
if (fs.existsSync(productHtmlPath)) {
|
||||
return res.sendFile(productHtmlPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if path is for public pages (root level pages)
|
||||
if (!req.path.includes("/admin/")) {
|
||||
let cleanPath = req.path.replace(/^\//, "").replace(/\.html$/, "");
|
||||
@@ -281,6 +313,8 @@ app.use((req, res, next) => {
|
||||
// Apply rate limiting to API routes
|
||||
app.use("/api/admin/login", authLimiter);
|
||||
app.use("/api/admin/logout", authLimiter);
|
||||
app.use("/api/customers/login", authLimiter);
|
||||
app.use("/api/customers/signup", authLimiter);
|
||||
app.use("/api", apiLimiter);
|
||||
|
||||
// API Routes
|
||||
@@ -288,6 +322,8 @@ app.use("/api/admin", authRoutes);
|
||||
app.use("/api/admin", adminRoutes);
|
||||
app.use("/api/admin/users", usersRoutes);
|
||||
app.use("/api/admin", uploadRoutes);
|
||||
app.use("/api/customers", customerAuthRoutes);
|
||||
app.use("/api/customers", customerCartRoutes);
|
||||
app.use("/api", publicRoutes);
|
||||
|
||||
// Admin static files (must be after URL rewriting)
|
||||
|
||||
Reference in New Issue
Block a user