3 min read
In this tutorial, we'll walk through creating a RESTful API using Node.js and Express. We'll build a simple books API that demonstrates core concepts like routing, middleware, error handling, and basic CRUD operations.
Prerequisites
- Node.js installed on your machine
- Basic understanding of JavaScript
- A code editor
- Postman or similar tool for testing APIs
Project Setup
First, create a new directory and initialize your project:
mkdir books-api
cd books-api
npm init -y
Install the necessary dependencies:
npm install express body-parser dotenv
Project Structure
Create the following file structure:
books-api/
├── src/
│ ├── routes/
│ │ └── books.js
│ ├── middleware/
│ │ └── errorHandler.js
│ └── server.js
├── package.json
└── .env
Basic Server Setup
Create src/server.js
:
const express = require('express');
const bodyParser = require('body-parser');
const booksRouter = require('./routes/books');
const errorHandler = require('./middleware/errorHandler');
// Initialize express app
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware
app.use(bodyParser.json());
// Routes
app.use('/api/books', booksRouter);
// Error handling middleware
app.use(errorHandler);
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Creating Routes
Create src/routes/books.js
:
const express = require('express');
const router = express.Router();
// In-memory database
let books = [
{ id: 1, title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' },
{ id: 2, title: '1984', author: 'George Orwell' }
];
// GET all books
router.get('/', (req, res) => {
res.json(books);
});
// GET book by ID
router.get('/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).json({ message: 'Book not found' });
res.json(book);
});
// POST new book
router.post('/', (req, res) => {
const book = {
id: books.length + 1,
title: req.body.title,
author: req.body.author
};
books.push(book);
res.status(201).json(book);
});
// PUT update book
router.put('/:id', (req, res) => {
const book = books.find(b => b.id === parseInt(req.params.id));
if (!book) return res.status(404).json({ message: 'Book not found' });
book.title = req.body.title || book.title;
book.author = req.body.author || book.author;
res.json(book);
});
// DELETE book
router.delete('/:id', (req, res) => {
const bookIndex = books.findIndex(b => b.id === parseInt(req.params.id));
if (bookIndex === -1) return res.status(404).json({ message: 'Book not found' });
books.splice(bookIndex, 1);
res.status(204).send();
});
module.exports = router;
Error Handling
Create src/middleware/errorHandler.js
:
function errorHandler(err, req, res, next) {
console.error(err.stack);
res.status(500).json({
message: 'Something went wrong!',
error: process.env.NODE_ENV === 'development' ? err.message : undefined
});
}
module.exports = errorHandler;
Input Validation
Let's add basic validation middleware for our POST requests:
const validateBook = (req, res, next) => {
if (!req.body.title || !req.body.author) {
return res.status(400).json({
message: 'Title and author are required'
});
}
next();
};
// Apply to POST route
router.post('/', validateBook, (req, res) => {
// ... existing post logic
});
Testing the API
Start your server:
node src/server.js
Use these curl commands to test your API:
# Get all books
curl http://localhost:3000/api/books
# Get single book
curl http://localhost:3000/api/books/1
# Create new book
curl -X POST -H "Content-Type: application/json" \
-d '{"title":"New Book","author":"John Doe"}' \
http://localhost:3000/api/books
# Update book
curl -X PUT -H "Content-Type: application/json" \
-d '{"title":"Updated Title"}' \
http://localhost:3000/api/books/1
# Delete book
curl -X DELETE http://localhost:3000/api/books/1
Next Steps
To enhance this basic API, consider:
- Adding a proper database (like MongoDB or PostgreSQL)
- Implementing authentication and authorization
- Implementing rate limiting
- Adding API documentation using Swagger
- Setting up automated testing
- Adding pagination for GET requests
- Implementing proper logging
Conclusion
You now have a working RESTful API built with Node.js and Express! This basic implementation demonstrates core concepts like routing, middleware, and error handling. While this example uses an in-memory array for storage, you can extend it by adding a database and implementing additional features as needed.
Remember to always:
- Validate input data
- Handle errors appropriately
- Follow REST conventions
- Implement proper security measures
- Document your API endpoints
Happy coding! 🚀
Related Posts
• 5 min read
APIs (Application Programming Interfaces) are the backbone of modern digital applications. They allow different software systems to communicate, exchange data, and collaborate seamlessly. As businesse...
• 4 min read
In today’s interconnected digital world, APIs (Application Programming Interfaces) are the backbone of communication between different software applications. From mobile apps to cloud services, APIs e...
• 5 min read
In the modern digital ecosystem, APIs (Application Programming Interfaces) serve as the backbone of connectivity. Whether you're building microservices, enabling integrations, or crafting data pipelin...