آنچه در این مقاله میخوانید
آموزش کار با Middleware در فریمورک Express.js
۱۸ اسفند ۱۳۹۹
در صورتی که با فریمورک Express.js فعالیت میکنید و قصد توسعه برنامههای وب حرفهای و مقیاسپذیر را دارید، بنابراین آشنایی با مفهوم Middleware امری بسیار ضروری برای شما خواهد بود. Middleware نقشی کلیدی در مدیریت درخواستها و پاسخها در Express ایفا میکند و بدون بهرهگیری از آن، امکان کنترل دقیق و شخصیسازی مسیرهای مختلف برنامه وجود نخواهد داشت.
در این راهنما از لیارا، به تعریف Middleware، تشریح نحوه عملکرد آن و معرفی انواع Middlewareهای پرکاربرد در پروژههای وب خواهیم پرداخت.
بدون هیچگونه پیکربندی پیچیده، هاست NodeJS را در چند ثانیه راهاندازی کنید!
✅ عملکرد بالا ✅ بدون نیاز به پیکربندی ✅ راهاندازی سریع
خرید هاست ابری NodeJS
آنچه در ادامه خواهید خواند:
- Middleware چیست؟
- نحوهی کار Middleware در برنامه
- راهاندازی یک API ساده با Express.js
- نحوهی استفاده از Express middlewareهای محبوب
- سوالات متداول
- جمع بندی
Middleware چیست؟
Middleware بخشی از فریمورک Express.js است که در طول چرخه درخواست و پاسخ request-response cycle، یعنی از زمان دریافت ریکوئست (request) در سرور، تا زمان ارسال ریسپانس (response)، اجرا میشود و به آبجکتهای درخواست و پاسخ دسترسیهای لازم را میدهد.
Express middleware در انواع و سطحهای مختلفی ارائه میشود:
- Application-level middleware
- Router-level middleware
- Error-handling middleware
- Built-in middleware
- Third-party middleware
اکثر توسعهدهندگان معمولا برای توسعه Express.js که امکانات محدودی دارد، از Middleware ها استفاده میکنند. شما میتوانید Middleware های اختصاصی خود را برای Express بنویسید، اما در بیشتر مواقع استفاده از ابزارهای داخلی (Built-in) یا Middleware های شخص ثالث (Third-party) انتخاب بهتری است.

نحوه کار Middleware در برنامه
فریمورک Express.js بهصورت پیشفرض امکانات محدودی را برای مدیریت درخواستها و پاسخها ارائه میدهد. به همین دلیل، توسعهدهندگان برای گسترش قابلیتهای این فریمورک و ساخت برنامههای وب، از مفهومی به نام Middleware استفاده میکنند.
Middleware در Express.js به بخشی از کد گفته میشود که در جریان پردازش هر درخواست، پیش از ارسال پاسخ نهایی اجرا و به اشیاء request
و response
دسترسیهای لازم را اعطا کند. این بخشهای میانی به توسعهدهندگان اجازه میدهد تا رفتار برنامهها را در مراحل مختلف پردازش درخواست، تغییر دهد.
برای درک بهتر، به مثالهای زیر توجه کنید:
- میتوان از Middleware برای بررسی اعتبار درخواستها و انجام فرآیند احراز هویت استفاده کرد.
- میتوان درخواستها و پاسخها را برای اهداف تحلیلی یا امنیتی در فایلهای ثبت وقایع (Log) ذخیره کرد.
- میتوان مدیریت خطاها و ارائه پاسخهای مناسب به کاربران را به کمک Middleware پیادهسازی کرد.
در Express.js این قابلیت وجود دارد تا توسعهدهندگان Middleware های اختصاصی خود را طراحی کنند، اما در بسیاری از پروژهها، استفاده از Middleware های آماده (اعم از ابزارهای داخلی یا کتابخانههای شخص ثالث) گزینهای سریع و مطمئنتری است.

البته موضوعی که در بالا به آن اشاره کردهایم. تنها یک مثال ساده برای درک بهتر مفهوم Middleware است. در یک سناریوی واقعی، معمولاً از چندین Middleware بهصورت زنجیرهای برای انجام یک فرایند واحد، مانند احراز هویت و ورود کاربر به سیستم استفاده میشود. این ساختار به توسعهدهندگان کمک میکند تا مراحل مختلف پردازش درخواست را به بخشهای مجزا و قابل مدیریت تقسیم کنند.
راه اندازی API ساده با Express.js
برای اینکه بتوانید نحوه استفاده از Middleware ها را بهتر درک کنید، لازم است تا یک نمونه API ساده با فریمورک Express بسازید. در ادامه، تمامی مراحل ایجاد و اجرای این API را توضیح خواهیم داد تا بتوانید به صورت عملی با Middleware ها کار کنید.
در اولین قدم باید تمامی دستورات زیر را بهترتیب در Terminal سیستمعامل خود وارد کنید.
mkdir express-api
cd express-api
npm init -y
دستور npm init -y
یک فایل به نام package.json
را در مسیر فعلی (پوشه express-api
) ایجاد میکند. این فایل اطلاعات اولیه پروژه را ذخیره میکند.
محتویات فایل به شکل زیر است.
{
"name": "express-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT"
}
حال برای نصب Express بایستی دستور زیر را اجرا کنید.
npm install express
با توجه به اینکه فایل اصلی (main) برنامه در این آموزش، index.js
است، لازم است فایلی را با همین نام در مسیر پروژه ایجاد کنید.
- در Linux:
touch index.js
- در Widnows:
.> index.js
پس از ایجاد فایل index.js
، برای ساخت یک Express API بایستی کدهای زیر را در آن فایل قرار دهید.
const express = require("express");
const app = express();
// Port
const port = 3000;
app.get("/", (req, res) => {
res.json({
message: "Hello Stranger! How are you?",
});
});
// Listen
app.listen(port, () => {
console.log(`Listening on port: ${port}`);
});
در مرحلهی بعد با اجرای دستور زیر، ابزار nodemon
را بهعنوان dev dependency پروژه نصب کنید.
npm install -D nodemon
با استفاده از این ابزار دیگر نیازی نیست تا هر مرتبه سرور Express.js خود را مجددا راهاندازی کنید؛ زیرا nodemon
تغییرات ایجاد شده را شناسایی کرده و به صورت خودکار سرور را راهاندازی میکند.
برای استفاده از این ابزار باید بخش "scripts"
را در فایل package.json
خود تغییر دهید.
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
},
پس از انجام تمامی مراحل بالا، فایل package.json
شما به شکل زیر خواهد بود.
{
"name": "express-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^2.0.6"
}
}
برای راهاندازی سرور میتوانید از دستور زیر استفاده کنید.
npm run dev
خروجی دستور وارد شده به صورت زیر است.
[nodemon] 2.0.5
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
Listening on port: 3000
پس از راهاندازی برنامه میتوانید از طریق آدرس localhost:3000، خروجی برنامه را مشاهده کنید.
{
"message": "Hello Stranger! How are you?"
}
Node.js چیست؟
Node.js
نحوه استفاده از Express middleware های محبوب
در مرحله قبل توانستید یک Express API ساده را راهاندازی کنید. حال در این بخش قصد داریم تا به بررسی و استفاده از پنج Express middleware محبوب بپردازیم. برای شناخت بیشتر ادامه مطلب را از دست ندهید.
1. Morgan
Morgan یک Middleware قدرتمند برای ثبت لاگ درخواستها در Express است. این ابزار به شما اجازه میدهد تا جزئیات هر درخواست ورودی به API را بهصورت خودکار ثبت کنید. یکی از مزایای مهم Morgan این است که میتوانید از فرمتهای پیشفرض برای لاگگیری استفاده کنید یا در صورت نیاز، ساختار گزارشها را بهدلخواه خود شخصیسازی کنید.
برای نصب morgan
، دستور زیر را اجرا کنید.
npm install morgan
morgan
فرمتهای از پیش تعریف شده بسیاری را دارد که میتوانید از آنها استفاده کنید. اما بسیاری از توسعهدهندگان ترجیح میدهند از خروجی استاندارد Log های Apache استفاده کنند.
برای استفاده از morgan
، فایل index.js
برنامه خود را به شکل زیر تغییر دهید.
const express = require("express");
const morgan = require("morgan")
const app = express();
// Middlewares
app.use(morgan("common"))
// Port
const port = 3000;
app.get("/", (req, res) => {
res.json({
message: "Hello Stranger! How are you?",
});
});
// Listen
app.listen(port, ()=>{
console.log(`Listening on port: ${port}`)
})
پس از اعمال تمامی تغییرات، کافی است برنامه را با استفاده از nodemon مجدداً اجرا کنید. از این لحظه به بعد، هر بار که یک درخواست به آدرس localhost:3000 ارسال میشود، Morgan اطلاعات مربوط به آن درخواست را در ترمینال نمایش میدهد.
::ffff:127.0.0.1 - - [14/Oct/2020:09:21:16 +0000] "GET / HTTP/1.1" 304 -
“لازم است به این نکته توجه کنید که Middleware ها دقیقاً به همان ترتیبی اجرا میشوند که در کد آنها را تعریف کردهاید بنابراین به این موضوع توجه زیادی داشته باشید.”
2. Helmet
Helmet یک Middleware کاربردی برای افزایش امنیت برنامههای Express.js است که با تنظیم Header های مناسب در پاسخهای HTTP، به بهبود امنیت کمک میکند. برای مشاهدهی عملکرد Helmet، ابتدا باید آدرس localhost:3000
را در مرورگر باز کنید. سپس با کلیدهای ترکیبی Ctrl + Shift + J
در مرورگر کروم یا Ctrl + Shift + K
در مرورگر فایرفاکس وارد کنسول مرورگر خود شوید و به بخش Network مراجعه کنید.

در صورتی که تب Network خالی بود، کلید F5
را فشار دهید تا صفحه مجددا بارگذاری شود و اطلاعات مربوط به درخواستها نمایش داده شوند.

در تصویر بالا میتوانید درخواست مربوط به favicon را نادیده بگیرید، زیرا در بخش دیگری به آن خواهیم پرداخت. در این مرحله تمرکز خود را بر روی درخواستهای GET مربوط به مسیر /
و بخش Response Header ها قرار دهید.

شاید در نگاه اول متوجه آسیبپذیری خاصی نشوید، اما نبود Header های امنیتی مناسب میتواند فرصتی را برای مهاجمان فراهم کند تا از این نقاط ضعف برای اجرای حملات خود استفاده کنند. بهعنوان مثال، وجود فیلدی با عنوان X-Powered-By: Express
نشان میدهد که برنامهی شما با فریمورک Express.js توسعه داده شده است و این موضوع میتواند مسیر شناسایی و سوءاستفاده از آسیبپذیریهای شناختهشده این فریمورک را برای مهاجمان سادهتر کند.
Helmet
مجموعهای از دوازده Middleware امنیتی است که به محافظت از برنامههای Express.js در برابر آسیب پذیریها و حملات رایج کمک میکند. برای استفاده از این ابزارها، ابتدا باید دستور زیر را برای نصب آن اجرا کنید.
npm install --save helmet
پس از نصب این ابزار باید تغییراتی را در فایل index.js
بهمنظور استفاده از helmet
ایجاد کنید.
const express = require("express");
const morgan = require("morgan")
const helmet = require("helmet");
const app = express();
// Middlewares
app.use(morgan("common"))
app.use(helmet());
// Port
const port = 3000;
app.get("/", (req, res) => {
res.json({
message: "Hello Stranger! How are you?",
});
});
// Listen
app.listen(port, () => {
console.log(`Listening on port: ${port}`);
});
پس از ایجاد تمامی تغییرات، آدرس localhost:3000 را مجددا باز کرده و به تب Network بروید.

همانطور که مشاهده میکنید، موارد جدیدی در Response Header ها تعریف شده است و همچنین فیلد X-Powered-By: Express
پاک شده است. به علاوه میتوانید helmet()
را به شکلی پیکربندی کنید تا برخی عملکردهای آن غیرفعال شود.
// This disables the `referrerPolicy` middleware but keeps the rest.
app.use(
helmet({
referrerPolicy: false,
})
);
3. CORS
CORS مخفف Cross-Origin Resource Sharing است و یکی از مفاهیم مهم در توسعهی برنامههای وب بهشمار میرود. در این بخش به شما آموزش خواهیم داد تا چگونه بتوانید CORS را در برنامههای Express.js فعال و بهدرستی پیکربندی کنید.
فرض کنید توسعهدهنده full-stack هستید و قسمت فرانتاند برنامه خود را با React بر روی پورت 3000 و قسمت بکاند را با Express روی پورت 8000 اجرا کردهاید. در این حالت، درخواستهایی که از فرانتاند به سرور بکاند ارسال میشود، به دلیل تفاوت مبدا (Origin) بین این دو پورت، با خطا مواجه خواهند شد. علت این خطا به محدودیتهای امنیتی مرورگرها بازمیگردد که مانع از ارسال درخواست به منابعی با مبدا متفاوت میشوند.

بنابراین بایستی سرور را بهصورتی پیکربندی کنید تا حتی درخواستها در مبداهای دیگر، پذیرفته شود. برای نصب cors
دستور زیر را اجرا کنید.
npm install --save cors
و پس از آن فایل index.js
را به شکل زیر تغییر دهید.
const express = require("express");
const morgan = require("morgan")
const helmet = require("helmet");
const cors = require("cors");
const app = express();
// Middlewares
app.use(morgan("common"))
app.use(helmet());
app.use(cors())
// Port
const port = 3000;
app.get("/", (req, res) => {
res.json({
message: "Hello Stranger! How are you?",
});
});
// Listen
app.listen(port, () => {
console.log(`Listening on port: ${port}`);
});
با اضافه کردن کد app.use(cors())
، برنامه تمامی درخواستها را از هر مبدا پذیرفته و به آنها پاسخهای لازم را میدهد. این موضوع در برخی موارد میتواند باعث آسیبپذیری برنامه شود. برای روشنتر شدن این موضوع، مثال قبلی را که شامل برنامهای با فرانتاند React و بکاند Express.js بود، مجدداً در نظر داشته باشید. به جای قبول کردن تمامی درخواستها از هر مبدا، میتوانیم یک وایت لیست (white list) از مبداهای معتبر ایجاد کنیم و تنها به درخواستهایی که از این مبداها ارسال میشوند، پاسخ دهیم.
// whitelist
const whitelist = ['http://localhost:3000', 'http://localhost:3001']
const corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
app.use(cors(corsOptions));

4. Express Rate Limit
Express Rate Limit یک Middleware در فریمورک Express.js است و امکان محدود کردن تعداد درخواستهای ارسالشده از یک آدرس IP را برای کاربران خود فراهم میکند. با استفاده از این Middleware میتوان از ارسال درخواستهای بیش از حد و مکرر جلوگیری کرده و از بار اضافی بر روی سرور و حملات احتمالی مانند حملات DoS محافظت کرد.
دستور زیر را برای نصب express-rate-limit
اجرا کنید.
npm install --save express-rate-limit
برای استفاده از این Middleware بایستی در فایل index.js
یک متغیر با نام limiter
ایجاد کرده و در ادامه از آن برای پیکربندی express-rate-limit
استفاده کنید.
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
با استفاده از کد بالا، هر آدرس IP مجاز است حداکثر 100 درخواست را طی بازه زمانی 15 دقیقه ارسال کند. پس از رسیدن به این حد، درخواستهای اضافی تا پایان آن بازه زمانی مسدود خواهد شد.
برای اعمال محدودیت فوق بایستی فایل index.js
را بهصورت زیر بهروزرسانی کنید.
const express = require("express");
const morgan = require("morgan")
const helmet = require("helmet");
const cors = require("cors");
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
const app = express();
// Middlewares
app.use(morgan("common"))
app.use(helmet());
app.use(cors())
app.use(limiter); // apply to all requests
// Port
const port = 3000;
app.get("/", (req, res) => {
res.json({
message: "Hello Stranger! How are you?",
});
});
// Listen
app.listen(port, () => {
console.log(`Listening on port: ${port}`);
});
برای درک بهتر میتوانید محدودیت زمانی و تعداد درخواستها را کااهش دهید.
const limiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 2, // limit each IP to 2 requests per windowMs
message: "Too many accounts created from this IP, please try again after a minute"
});
حال اگر وارد آدرس localhost:3000 شوید و صفحهها را چندین مرتبه بهصورت متوالی رفرش کنید، پیغام Too many accounts created from this IP, please try again after a minute
به شما نمایش میدهد.
از آنجایی که morgan
فعال است، میتوانید گزارشها را در Terminal مشاهده کنید.
::1 - - [14/Nov/2020:08:15:58 +0000] "GET / HTTP/1.1" 304 -
::1 - - [14/Nov/2020:08:15:59 +0000] "GET / HTTP/1.1" 304 -
::1 - - [14/Nov/2020:08:15:59 +0000] "GET / HTTP/1.1" 429 71
کد 429 نشان میدهد کاربر درخواستهای زیادی را بهنسبت مدت زمان مشخص شده، ارسال کردهاند.
میتوانید express-rate-limit را تنظیم کنید تا تنها درخواستهای مسیرهای خاص را محدود کند.
// apply to all requests
app.use(limiter);
// only apply to requests that begin with /api/
app.use("/api/", limiter);
در لیست زیر میتوانید تعدادی از Middleware هایی که برای محدود کردن تعداد درخواستها از آنها استفاده میشوند را مشاهده کنید:
5. serve-favicon
serve-favicon
یک Middleware در Express.js است که برای ارسال فایل favicon به مرورگر از آن استفاده میشود. احتمالاً به یاد دارید که در بخشهای قبلی، در تب Network یک درخواست ناموفق برای favicon مشاهده کردهایم.

favicon یک آیکون کوچک است که اغلب در سمت چپ عنوان صفحه در نوار آدرس نمایش داده میشود. حال برای نصب serve-favicon
از دستور زیر استفاده کنید.
npm install serve-favicon
همچنین به یک favicon در مسیر پروژه نیاز خواهید داشت. پس از قراردادن favicon در مسیر پروژه میتوانید فایل index.js
را به شکل زیر بهروزرسانی کنید.
const express = require("express");
const morgan = require("morgan")
const helmet = require("helmet");
const cors = require("cors");
const rateLimit = require("express-rate-limit");
var favicon = require('serve-favicon')
const limiter = rateLimit({
windowMs: 15 *60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many accounts created from this IP, please try again after a minute"
});
const app = express();
// Serve Favicon
app.use(favicon('favicon.ico'))
// Middlewares
app.use(morgan("common"))
app.use(helmet());
app.use(cors())
app.use(limiter); // apply to all requests
// Port
const port = 3000;
app.get("/", (req, res) => {
res.json({
message: "Hello Stranger! How are you?",
});
});
// Listen
app.listen(port, () => {
console.log(`Listening on port: ${port}`);
});
اگر favicon شما در فایل public
قرار داشته باشد میتوانید از path
استفاده کنید.
var path = require('path')
...
// Serve Favicon
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
...
حال اگر آدرس localhost:3000 را مجددا بارگیری کنید، favicon انتخابی شما نمایش داده میشود.

تب Network را باز کرده و صفحه را reload کنید.

با استفاده از serve-favicon میتوانید فایل favicon سایت خود را به مرورگر ارسال و در حافظه کش کاربر ذخیره کنید. این کار باعث بهتر ساختن عملکرد وبسایت میشود؛ زیرا مرورگر بهصورت پیشفرض آیکون را تا یک سال در کش نگه میدارد و برای دفعات بعدی نیازی به بارگذاری مجدد آن نیست.
Cache-Control: public, max-age=31536000
اما برای تغییر این مدت زمان میتوانید از مقدار maxAge
استفاده کنید.
// Serve Favicon
app.use(
favicon("favicon.ico", {
maxAge: 500 * 60 * 60 * 24 * 1000,
})
);
معرفی هاست رایگان Node.js
هاست رایگان Node.js
سوالات متداول
در ادامه به سوالاتی که امکان دارد در این زمینه برای شما بدون پاسخ بماند، جوابهای کوتاه اما مفیدی دادهایم که با استفاده از آن میتوانید به سوال خود پاسخ صحیحی را بدهید.
Middleware چیست و چرا در Express.js از آن استفاده میشود؟
Middleware قطعه کدی است که بین دریافت ریکوئست و ارسال ریسپانس اجرا میشود و وظیفه پردازش، تغییر یا مدیریت درخواستها و پاسخها را دارد.
چگونه می توان Middleware اختصاصی در Express.js نوشت؟
برای این عمل کافی است تابعی بنویسید که سه پارامتر req , res و next را بگیرد و بعد از پردازش، با فراخوانی next به Middleware بعدی منتقل شود.
تفاوت Middleware داخلی (Built-in) و شخص ثالث (Third-party) چیست؟
Middleware داخلی به صورت پیشفرض در Express وجود دارد، در حالی که Middleware شخص ثالث توسط جامعه توسعهدهندگان ساخته شده و بایستی بهصورت جداگانه نصب شود.
آیا ترتیب تعریف Middleware ها اهمیت دارد؟
بله، Middleware ها به ترتیبی که تعریف شدهاند اجرا میشوند و ترتیب اشتباه ممکن است باعث بروز خطا یا کار نکردن صحیح برنامه شود.
چگونه می توان محدودیت تعداد درخواست ها را با Middleware تنظیم کرد؟
با استفاده از Middleware هایی مانند express-rate-limit میتوان تعداد درخواستهای تکراری از یک IP را در بازه زمانی مشخص محدود کرد.
جمع بندی
Middleware ها بخش مهم و جداییناپذیر فریمورک Express.js هستند که در مدیریت بهتر درخواستها و پاسخها نقش بزرگی را ایفا میکنند. با استفاده از Middleware ها میتوان امنیت، کارایی و قابلیت توسعه برنامههای وب را به شکل شگفتانگیزی افزایش داد. یادگیری نحوه نوشتن و استفاده صحیح از Middleware ها برای هر توسعهدهنده Express بسیار ضروری است.
نحوه نصب Node.js روی سرور مجازی اوبونتو Ubuntu
نصب Node.js روی سرور مجازی اوبونتو
منبع: https://blog.logrocket.com/express-middleware-a-complete-guide