ساخت RESTful API در Node.js
RESTful API یکی از پراستفادهترین الگوها برای ارتباط کلاینت و سرور است. در اکوسیستم Node.js، فریمورک Express همراه با ابزارهایی مثل Mongoose (برای MongoDB)، بستههای اعتبارسنجی، و middlewareها باعث میشوند ساخت یک API امن، مقیاسپذیر و قابل تست سادهتر شود. در این مقاله قدمبهقدم مفاهیم کلیدی، الگوهای طراحی و مثالهای عملی را بررسی میکنیم.
ویژگیهای مهم یک RESTful API خوب
- ساختار منطقی و منابع مشخص (نقش URLها)
- استفاده از متدهای HTTP مناسب (GET, POST, PUT/PATCH, DELETE)
- حالتهای پاسخدهی استاندارد با HTTP Status Codes
- اعتبارسنجی ورودیها و مدیریت خطا
- امنیت: احراز هویت، مجوزها، و جلوگیری از حملات رایج
- مقیاسپذیری و قابلیت کشینگ/لاگینگ
نمونه ساختار پروژه
یک ساختار ساده اما موثر:
- server.js — نقطه ورود
- routes/ — تعریف مسیرها
- controllers/ — منطق تجاری
- models/ — اسکیمای دیتابیس
- middleware/ — اعتبارسنجی، احراز هویت، خطایاب
نمونه پایه: server.js با Express
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const helmet = require('helmet');
const routes = require('./routes');
const app = express();
app.use(helmet());
app.use(cors());
app.use(express.json());
app.use('/api', routes);
// Global error handler
app.use((err, req, res, next) => {
console.error(err);
res.status(err.status || 500).json({ error: err.message || 'Internal Server Error' });
});
const PORT = process.env.PORT || 3000;
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => app.listen(PORT, () => console.log('Server running on port', PORT)))
.catch(err => console.error('DB connection error', err));این کد یک اپ ساده Express راهاندازی میکند، هدرهای امنیتی پایه را با helmet اضافه میکند، CORS فعال میسازد، و JSON ورودی را پارس میکند. سپس روتهای API را روی مسیر /api قرار میدهد و یک error handler سراسری برای مدیریت خطاها ثبت میکند. همچنین اتصال به MongoDB قبل از گوش کردن به پورت انجام میشود.
مدل داده با Mongoose
const mongoose = require('mongoose');
const PostSchema = new mongoose.Schema({
title: { type: String, required: true, trim: true },
body: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
tags: [String],
createdAt: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Post', PostSchema);این اسکیمای ساده یک مدل Post را تعریف میکند که برای CRUD پستها در یک بلاگ مناسب است. نکاتی مثل trim، required و ارجاع به مدل User نشاندهنده روابط بین منابع هستند.
مسیرها و کنترلرها (CRUD)
const express = require('express');
const router = express.Router();
const Post = require('../models/Post');
// Create
router.post('/posts', async (req, res, next) => {
try {
const post = await Post.create(req.body);
res.status(201).json(post);
} catch (err) { next(err); }
});
// Read (list with pagination)
router.get('/posts', async (req, res, next) => {
try {
const page = Math.max(1, parseInt(req.query.page) || 1);
const limit = Math.min(100, parseInt(req.query.limit) || 10);
const posts = await Post.find()
.skip((page - 1) * limit)
.limit(limit)
.sort({ createdAt: -1 });
res.json(posts);
} catch (err) { next(err); }
});
// Read (single)
router.get('/posts/:id', async (req, res, next) => {
try {
const post = await Post.findById(req.params.id);
if (!post) return res.status(404).json({ error: 'Not found' });
res.json(post);
} catch (err) { next(err); }
});
// Update
router.put('/posts/:id', async (req, res, next) => {
try {
const post = await Post.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
if (!post) return res.status(404).json({ error: 'Not found' });
res.json(post);
} catch (err) { next(err); }
});
// Delete
router.delete('/posts/:id', async (req, res, next) => {
try {
const post = await Post.findByIdAndDelete(req.params.id);
if (!post) return res.status(404).json({ error: 'Not found' });
res.status(204).end();
} catch (err) { next(err); }
});
module.exports = router;در این مثال، مسیرها به صورت RESTful تعریف شدهاند: استفاده از متدهای HTTP برای عملیات CRUD، پیادهسازی صفحهبندی ساده و بازگرداندن کدهای وضعیت مناسب. هر خطا به middleware خطا فرستاده میشود تا مدیریت مرکزی شود.
الگو: async wrapper برای جلوگیری از تکرار try/catch
const asyncHandler = fn => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
router.get('/posts/:id', asyncHandler(async (req, res) => {
const post = await Post.findById(req.params.id);
if (!post) return res.status(404).json({ error: 'Not found' });
res.json(post);
}));تابع asyncHandler به صورت عمومی برای بستهبندی توابع async استفاده میشود تا نیاز به نوشتن try/catch در هر مسیر حذف شود و خطاها مستقیم به error handler ارسال شوند.
احراز هویت با JWT و middleware
const jwt = require('jsonwebtoken');
const auth = (req, res, next) => {
const header = req.headers.authorization;
if (!header) return res.status(401).json({ error: 'No token' });
const token = header.split(' ')[1];
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
req.user = payload;
next();
} catch (err) {
res.status(401).json({ error: 'Invalid token' });
}
};
module.exports = auth;این middleware توکن را از هدر Authorization میخواند، آن را بررسی میکند و در صورت معتبر بودن، اطلاعات کاربر را در req.user قرار میدهد. سپس میتوان از این middleware برای محافظت از روتهای خصوصی استفاده کرد.
بهبودها، امنیت و بهینهسازی
- اعتبارسنجی ورودی: از کتابخانههایی مثل Joi یا express-validator استفاده کنید.
- Rate Limiting: جلوگیری از حملات DDoS با
express-rate-limit. - Logging و Monitoring: استفاده از winston یا سرویسهای APM.
- Caching: پاسخهای غیر داینامیک را با Redis کش کنید.
- مهاجرت داده و ایندکسها: برای کوئریهای سنگین، ایندکس مناسب در MongoDB تعریف کنید.
جدول مرجع سریع متدها و کد وضعیت
| HTTP Method | معنی |
|---|---|
| GET | خواندن داده |
| POST | ایجاد منابع |
| PUT/PATCH | بهروزرسانی |
| DELETE | حذف |
| Status Code | معنی |
|---|---|
| 200 | OK |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 404 | Not Found |
| 500 | Internal Server Error |
تست، مستندسازی و انتشار
- تست واحد و انتها-به-انتها: از Jest و Supertest برای تست API استفاده کنید.
- مستندسازی: OpenAPI (Swagger) برای توصیف و تولید مستندات تعاملی.
- CI/CD: اجرای تستها و استقرار خودکار با GitHub Actions یا GitLab CI.
جمعبندی و نکات مهم
ساخت RESTful API در Node.js ترکیبی از طراحی خوب، امنیت و عملیات صحیح است. با استفاده از ساختار ماژولار (routes/controllers/models)، مدیریت خطا مرکزی، و middlewareهای استاندارد میتوانید APIهایی قابل نگهداری و مقیاسپذیر بسازید. توجه ویژه به اعتبارسنجی ورودی، احراز هویت، لاگینگ و تست اتوماتیک کیفیت سرویس شما را بالا میبرد.
آیا این مطلب برای شما مفید بود ؟




