Can you help me build a REST API with Node.js and Express? I need authentication, rate limiting, and proper error handling.
Absolutely! Here's a production-ready Express.js setup with JWT authentication, rate limiting via `express-rate-limit`, and centralized error handling:
const express = require('express');
const rateLimit = require('express-rate-limit');
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());
// Rate limiting — 100 requests per 15 minutes per IP
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
// JWT auth middleware
const authenticate = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token provided' });
try {
req.user = jwt.verify(token, process.env.JWT_SECRET);
next();
} catch {
res.status(401).json({ error: 'Invalid or expired token' });
}
};
// Centralized error handler
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
error: err.message || 'Internal server error',
...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
});
});
app.listen(3000, () => console.log('Server running on :3000'));This setup gives you a solid foundation. Want me to add specific route examples, database integration with Prisma, or Docker configuration next?
Yes, add Prisma integration with a User model and the login/register endpoints.
Here's the Prisma schema and the auth endpoints:
// schema.prisma
model User {
id String @id @default(cuid())
email String @unique
password String
name String?
role Role @default(USER)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum Role {
USER
ADMIN
}And the register/login route handlers with bcrypt password hashing:
const bcrypt = require('bcryptjs');
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
// POST /api/auth/register
app.post('/api/auth/register', async (req, res, next) => {
try {
const { email, password, name } = req.body;
const existing = await prisma.user.findUnique({ where: { email } });
if (existing) return res.status(409).json({ error: 'Email already registered' });
const hashed = await bcrypt.hash(password, 12);
const user = await prisma.user.create({
data: { email, password: hashed, name },
select: { id: true, email: true, name: true, role: true },
});
const token = jwt.sign({ userId: user.id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '7d' });
res.status(201).json({ user, token });
} catch (err) { next(err); }
});ChatAI can make mistakes. Verify important information from reliable sources.