Let’s rewrite the same practices using Express.js, the go-to framework for building APIs in Node.js.
1. Foundational Design & Security 🛡️
Start with the basics: secure your API like it’s your grandma’s cookie recipe 🍪.
Authentication & Authorization 🔒
- Authentication: Who are you? (Use tokens like JWTs)
- Authorization: What are you allowed to do? (Role-based access control)
Example: Token Validation
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const SECRET_KEY = "supersecretkey";
app.get('/protected', (req, res) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: "Token missing" });
}
try {
jwt.verify(token, SECRET_KEY);
res.status(200).json({ message: "Access granted" });
} catch (err) {
res.status(403).json({ error: "Invalid or expired token" });
}
});
Token validation like:
- No token? 🚫
401 Unauthorized
- Invalid token? 🚓
403 Forbidden
Rate Limiter 🚦
Prevent abuse by limiting the number of requests per user.
Example:
- First 100 requests: 🏎️ Smooth sailing.
- After 101st request: 🐢 Slow down, buddy.
Use express-rate-limit to limit requests.
Example:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 5, // Limit each IP to 5 requests
message: "Too many requests, please try again later.",
});
app.use('/limited', limiter, (req, res) => {
res.json({ message: "You are within the limit!" });
});
CORS Validation 🌐
Allow requests from trusted origins only.
Example:
const cors = require('cors');
app.use(cors({
origin: 'https://trusted-site.com',
}));
Trying from an untrusted site?
Response:
"Sorry, not today! 🙅"
2. API Structure & Operations 🏗️
Clear CRUD Endpoints 🛠️
Examples:
GET /users– Get all users 👥
POST /users– Create a new user ✍️
PUT /users/{id}– Update user 🛠️
DELETE /users/{id}– Delete user 🗑️
Confusing endpoints = confused developers = angry developers.
Manage users resource with Express.
Example:
let users = [];
app.use(express.json());
app.get('/users', (req, res) => {
res.json(users);
});
app.post('/users', (req, res) => {
const user = req.body;
users.push(user);
res.status(201).json(user);
});
app.put('/users/:id', (req, res) => {
const id = parseInt(req.params.id);
const user = users.find(u => u.id === id);
if (user) {
Object.assign(user, req.body);
res.json(user);
} else {
res.status(404).json({ error: "User not found" });
}
});
app.delete('/users/:id', (req, res) => {
users = users.filter(u => u.id !== parseInt(req.params.id));
res.status(204).send();
});
Status-Based Responses 📜
Always tell users what’s happening, politely.
Examples:
200 OK– Yay, it worked! 🎉
201 Created– Your shiny new resource is ready! 🚀
400 Bad Request– Uh-oh, something’s wrong with your input. 🤷
500 Internal Server Error– Oops, we broke something. 😓
API Documentation 📚
Use tools like Swagger or Postman.
Why?
Because an undocumented API is like IKEA furniture with no manual. 😭
Consistent Naming Conventions 📏
Stick to a pattern and never mix styles.
Example:
- Good:
/api/products
- Bad:
/API/getProducts
- Ugly:
/api/v1/proDuctsGetNow
3. Performance & Scalability 🚀
Caching Strategy 🧊
Cache responses to save time (and server tears 😢).
Example:
GET /api/cached
Cache-Control: max-age=3600
Use
node-cacheto cache responses.
Example:
const NodeCache = require('node-cache');
const cache = new NodeCache();
app.get('/cached', (req, res) => {
const key = 'cachedResponse';
if (cache.has(key)) {
return res.json(cache.get(key));
}
const data = { message: "This response is cached!" };
cache.set(key, data, 60); // Cache for 60 seconds
res.json(data);
});
Blue/Green Deployment 🌏💚
Deploy without breaking anything. Test on a “blue” version while users stay on “green.”
Steps:
- Deploy the “blue” environment.
- Test it.
- Gradually switch traffic to blue.
- Celebrate with cake 🎂.
Logging Mechanism 📝
Log all requests using
morgan.
Pro Tip:
Logs should be helpful, not a novel. Nobody likes wading through War and Peace. 🫠
Example:
const morgan = require('morgan');
app.use(morgan('combined'));
4. Quality Assurance 🧪
Comprehensive Test Cases ✅
Test every scenario, even the absurd ones.
Example:
- Does the API handle invalid inputs?
- What happens if someone tries to upload a cat picture to
/users? 🐱
Error Handling 🚨
Be friendly, even when rejecting users.
Example:
Input Validation 🛂
Validate everything. Trust no one.
Example:
- User sends
"age": "twenty". - Response:
"Age must be a number."
Conclusion:
A great API isn’t just functional; it’s intuitive, secure, and scalable. Treat your API like your house: keep it clean, secure, and easy to navigate. 🏠✨
And remember: Developers using your API will silently thank you (and maybe buy you coffee ☕). Or, if you ignore best practices, you might just end up on their “wall of shame.” 🙃
What’s your favorite REST API best practice? Share below!👇 Let’s chat! 🎉
SOCIAL SHARE CARD GENERATOR