Node.js: Express Framework and RESTful APIs
What is Express?
Express is a minimal, unopinionated web framework for Node.js that simplifies building servers, routing, and APIs on top of the core http module.
npm install express
A Basic Express Server
const express = require('express');
const app = express();
app.use(express.json()); // parse JSON request bodies
app.get('/', (req, res) => {
res.send('Hello from Express!');
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Routing
Express maps HTTP methods and URL paths to handler functions.
app.get('/users', (req, res) => {
res.json([{ id: 1, name: 'Alice' }]);
});
app.post('/users', (req, res) => {
const newUser = req.body;
res.status(201).json(newUser);
});
app.put('/users/:id', (req, res) => {
res.json({ id: req.params.id, ...req.body });
});
app.delete('/users/:id', (req, res) => {
res.status(204).send();
});
// Route parameters and query strings
app.get('/products/:category', (req, res) => {
console.log(req.params.category); // /products/electronics -> "electronics"
console.log(req.query.sort); // ?sort=price -> "price"
res.send('OK');
});
Middleware
Middleware functions run between the request and the final handler — used for logging, authentication, parsing, error handling.
// Custom middleware: runs for every request
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next(); // pass control to the next middleware/handler
});
// Middleware scoped to a specific route
function authenticate(req, res, next) {
if (req.headers.authorization) {
next();
} else {
res.status(401).json({ error: 'Unauthorized' });
}
}
app.get('/admin', authenticate, (req, res) => {
res.send('Welcome, admin!');
});
Building a RESTful API
REST (Representational State Transfer) is an architectural style where each URL represents a resource, and HTTP methods define the action on it.
| HTTP Method | URL | Action |
|---|---|---|
| GET | /api/books | List all books |
| GET | /api/books/:id | Get one book |
| POST | /api/books | Create a book |
| PUT | /api/books/:id | Update a book |
| DELETE | /api/books/:id | Delete a book |
const express = require('express');
const app = express();
app.use(express.json());
let books = [{ id: 1, title: 'Clean Code' }];
app.get('/api/books', (req, res) => res.json(books));
app.get('/api/books/:id', (req, res) => {
const book = books.find(b => b.id == req.params.id);
if (!book) return res.status(404).json({ error: 'Not found' });
res.json(book);
});
app.post('/api/books', (req, res) => {
const book = { id: books.length + 1, ...req.body };
books.push(book);
res.status(201).json(book);
});
app.put('/api/books/:id', (req, res) => {
const index = books.findIndex(b => b.id == req.params.id);
if (index === -1) return res.status(404).json({ error: 'Not found' });
books[index] = { ...books[index], ...req.body };
res.json(books[index]);
});
app.delete('/api/books/:id', (req, res) => {
books = books.filter(b => b.id != req.params.id);
res.status(204).send();
});
app.listen(3000, () => console.log('REST API running on port 3000'));
REST Best Practices
- Use nouns, not verbs, in URLs (
/books, not/getBooks) - Use proper HTTP status codes (200, 201, 400, 404, 500)
- Version your API (
/api/v1/books) - Return JSON consistently
- Use plural resource names
Key Takeaway: Express simplifies routing and middleware on top of Node's http module. RESTful APIs map HTTP methods (GET/POST/PUT/DELETE) to CRUD operations on named resources, returning JSON with proper status codes.