Building RESTful APIs with Node.js and Express
Node.js and Express provide a powerful combination for building scalable web APIs. In this guide, we'll create a complete RESTful API from scratch.
Setting Up Your Project
First, let's initialize a new Node.js project:
npm init -y
npm install express cors helmet morgan
npm install -D nodemon
Basic Express Server
Create a simple Express server:
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware
app.use(helmet());
app.use(cors());
app.use(morgan('combined'));
app.use(express.json());
// Routes
app.get('/api/health', (req, res) => {
res.json({ status: 'OK', timestamp: new Date().toISOString() });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Creating RESTful Routes
Let's build a complete CRUD API for a "users" resource:
// In-memory storage (use a database in production)
let users = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
];
// GET /api/users - Get all users
app.get('/api/users', (req, res) => {
res.json(users);
});
// GET /api/users/:id - Get user by ID
app.get('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.json(user);
});
// POST /api/users - Create new user
app.post('/api/users', (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({ error: 'Name and email are required' });
}
const newUser = {
id: users.length + 1,
name,
email
};
users.push(newUser);
res.status(201).json(newUser);
});
// PUT /api/users/:id - Update user
app.put('/api/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
const { name, email } = req.body;
if (name) user.name = name;
if (email) user.email = email;
res.json(user);
});
// DELETE /api/users/:id - Delete user
app.delete('/api/users/:id', (req, res) => {
const userIndex = users.findIndex(u => u.id === parseInt(req.params.id));
if (userIndex === -1) {
return res.status(404).json({ error: 'User not found' });
}
users.splice(userIndex, 1);
res.status(204).send();
});
Error Handling Middleware
Add proper error handling:
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
});
// 404 handler
app.use('*', (req, res) => {
res.status(404).json({ error: 'Route not found' });
});
Testing Your API
Test your endpoints using curl or Postman:
# Get all users
curl http://localhost:3000/api/users
# Create a new user
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Bob Johnson","email":"bob@example.com"}'
# Update a user
curl -X PUT http://localhost:3000/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"John Updated"}'
Best Practices
- Use environment variables for configuration
- Implement proper authentication and authorization
- Add input validation with libraries like Joi
- Use a real database (MongoDB, PostgreSQL, etc.)
- Implement rate limiting and security measures
- Add comprehensive logging and monitoring
This foundation will help you build robust APIs that can scale with your application needs!