step 10.7: done
This commit is contained in:
+30
-1
@@ -99,12 +99,19 @@ function createApp() {
|
||||
app.get('/api/heroes/:name', heroProfileRoutes.getHeroProfile);
|
||||
|
||||
// Catch-all: serve 404 page for unknown paths (HTML requests only).
|
||||
// API paths still return JSON errors via the central handler.
|
||||
// API paths (/api/*) always return JSON errors, never HTML.
|
||||
// Placed before static files so it intercepts non-file paths.
|
||||
const PUBLIC_DIR = path.resolve(__dirname, '../public');
|
||||
app.use((req, res, next) => {
|
||||
// If a route already set headers, let it through (e.g., static file not found)
|
||||
if (res.headersSent) return next();
|
||||
// API paths always return JSON, regardless of Accept header
|
||||
if (req.path.startsWith('/api/')) {
|
||||
return res.status(404).json({
|
||||
ok: false,
|
||||
error: { code: 'NOT_FOUND', message: 'Resource not found.' },
|
||||
});
|
||||
}
|
||||
if (req.accepts('html')) {
|
||||
return res.status(404).sendFile(path.join(PUBLIC_DIR, '404.html'));
|
||||
}
|
||||
@@ -134,6 +141,28 @@ function createApp() {
|
||||
});
|
||||
}
|
||||
|
||||
// Express JSON parser: malformed JSON → 400
|
||||
if (err instanceof SyntaxError && err.status === 400) {
|
||||
return res.status(400).json({
|
||||
ok: false,
|
||||
error: {
|
||||
code: 'INVALID_JSON',
|
||||
message: 'Malformed JSON in request body.',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Express JSON parser: body exceeds size limit → 413
|
||||
if (err.status === 413) {
|
||||
return res.status(413).json({
|
||||
ok: false,
|
||||
error: {
|
||||
code: 'PAYLOAD_TOO_LARGE',
|
||||
message: 'Request body exceeds the maximum allowed size.',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Check for Zod-like validation errors
|
||||
if (err.name === 'ZodError' || (err.errors && Array.isArray(err.errors))) {
|
||||
return res.status(400).json({
|
||||
|
||||
+6
-2
@@ -47,7 +47,9 @@ async function handleRegister(req, res) {
|
||||
|
||||
// Regenerate session to prevent fixation
|
||||
req.session.regenerate((err) => {
|
||||
if (err) throw new AppError('INTERNAL_ERROR', 'Session regeneration failed.', 500);
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
req.session.userId = user.id;
|
||||
req.session.username = user.username;
|
||||
res.status(201).json({ ok: true, data: { user: { id: user.id, username: user.username } } });
|
||||
@@ -65,7 +67,9 @@ async function handleLogin(req, res) {
|
||||
|
||||
// Regenerate session to prevent fixation
|
||||
req.session.regenerate((err) => {
|
||||
if (err) throw new AppError('INTERNAL_ERROR', 'Session regeneration failed.', 500);
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
req.session.userId = user.id;
|
||||
res.json({ ok: true, data: { user: { id: user.id, username: user.username }, hasHero: userHasHero(user.id) } });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user