Merge pull request 'fix: Prevent /static and /uploads paths from falling through to React catch-all' (#18) from feat/header-logo-and-title-gradient into master

Reviewed-on: #18
This commit was merged in pull request #18.
This commit is contained in:
2026-03-09 19:11:32 -05:00

View File

@@ -36,10 +36,15 @@ app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Static file serving
// Static asset routes — registered BEFORE React catch-all so they are
// resolved directly and never fall through to index.html
app.use('/uploads', express.static(UPLOAD_PATH));
app.use('/static', express.static(STATIC_PATH));
// Explicit 404 for missing asset files so the catch-all never intercepts them
app.use('/uploads', (req, res) => res.status(404).json({ error: 'Upload not found' }));
app.use('/static', (req, res) => res.status(404).json({ error: 'Static asset not found' }));
// API Routes
app.use('/api/dogs', require('./routes/dogs'));
app.use('/api/litters', require('./routes/litters'));
@@ -53,11 +58,15 @@ app.get('/api/health', (req, res) => {
});
// Serve React frontend in production
// The catch-all is intentionally placed AFTER all asset/API routes above.
// express.static(clientBuildPath) handles real build assets (JS/CSS chunks).
// The scoped '*' only fires for HTML5 client-side routes (e.g. /dogs, /litters).
if (process.env.NODE_ENV === 'production') {
const clientBuildPath = path.join(__dirname, '../client/dist');
app.use(express.static(clientBuildPath));
app.get('*', (req, res) => {
// Only send index.html for non-asset, non-api paths
app.get(/^(?!\/(api|static|uploads)\/).*$/, (req, res) => {
res.sendFile(path.join(clientBuildPath, 'index.html'));
});
}