Creating a RESTful API with Node.js and Express
Creating a RESTful API with Node.js and Express
In this post, I'll walk through the process of building a simple but robust RESTful API using Node.js and Express.
Why Build an API?
Before diving into the code, let's discuss why you might want to build your own API:
- To provide data to front-end applications
- To create a microservice architecture
- To practice backend development skills
- To integrate with third-party services
Setting Up the Project
First, let's initialize a new Node.js project and install the necessary dependencies:
mkdir rest-api-demo
cd rest-api-demo
npm init -y
npm install express mongoose dotenv cors helmet
npm install nodemon --save-dev
Project Structure
I organized my project with the following structure:
rest-api-demo/
├── config/
│ └── db.js
├── controllers/
│ └── productController.js
├── models/
│ └── Product.js
├── routes/
│ └── productRoutes.js
├── .env
├── .gitignore
├── app.js
└── package.json
Creating the Express Server
Here's the basic setup for our Express server in app.js
:
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const connectDB = require('./config/db');
require('dotenv').config();
// Connect to database
connectDB();
const app = express();
// Middleware
app.use(helmet());
app.use(cors());
app.use(express.json());
// Routes
app.use('/api/products', require('./routes/productRoutes'));
// Root route
app.get('/', (req, res) => {
res.json({ message: 'Welcome to the API' });
});
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Server error' });
});
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Implementing CRUD Operations
In controllers/productController.js
, I implemented all the CRUD operations:
const Product = require('../models/Product');
// Get all products
exports.getProducts = async (req, res) => {
try {
const products = await Product.find();
res.status(200).json({ success: true, count: products.length, data: products });
} catch (error) {
res.status(400).json({ success: false, error: error.message });
}
};
// Get single product
exports.getProduct = async (req, res) => {
try {
const product = await Product.findById(req.params.id);
if (!product) {
return res.status(404).json({ success: false, error: 'Product not found' });
}
res.status(200).json({ success: true, data: product });
} catch (error) {
res.status(400).json({ success: false, error: error.message });
}
};
// Create new product
exports.createProduct = async (req, res) => {
try {
const product = await Product.create(req.body);
res.status(201).json({ success: true, data: product });
} catch (error) {
res.status(400).json({ success: false, error: error.message });
}
};
// Update product
exports.updateProduct = async (req, res) => {
try {
const product = await Product.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true, runValidators: true }
);
if (!product) {
return res.status(404).json({ success: false, error: 'Product not found' });
}
res.status(200).json({ success: true, data: product });
} catch (error) {
res.status(400).json({ success: false, error: error.message });
}
};
// Delete product
exports.deleteProduct = async (req, res) => {
try {
const product = await Product.findByIdAndDelete(req.params.id);
if (!product) {
return res.status(404).json({ success: false, error: 'Product not found' });
}
res.status(200).json({ success: true, data: {} });
} catch (error) {
res.status(400).json({ success: false, error: error.message });
}
};
Lessons Learned
Building this API taught me several important concepts:
- Proper Error Handling - Implementing try/catch blocks for all async operations
- RESTful Design - Following REST conventions for endpoints
- Code Organization - Using the MVC pattern to separate concerns
- Middleware Usage - Leveraging Express middleware for security and parsing
Next Steps
In future iterations, I plan to add:
- Authentication with JWT
- Rate limiting
- Request validation
- Pagination and filtering
- Automated testing
Have you built a RESTful API before? What challenges did you face?