بازنویسی API در Express و استفاده از Template Engineها

Express.js یک فریم‌ورک مینیمال و انعطاف‌پذیر است که بخش زیادی از قابلیت‌های آن از طریق متدها و ویژگی‌های موجود در request و response ارائه می‌شود. این متدها و ویژگی‌ها از طریق prototype به ارث می‌رسند و همین موضوع امکان بازنویسی (Override) و گسترش (Extend) API را فراهم می‌کند. علاوه بر این، Express از سیستم Template Engine پشتیبانی می‌کند تا بتوان صفحات HTML را به‌صورت پویا تولید کرد. این مقاله هر دو موضوع—بازنویسی API و استفاده از Template Engine—را به‌صورت کامل و کاربردی توضیح می‌دهد.

Express API Overrideexpress.request / express.responseapp.request / app.responseTemplate EnginePug / EJS / HandlebarsPrototype Extension

~3 دقیقه مطالعه • بروزرسانی ۵ دی ۱۴۰۴

1. بازنویسی API در Express


Express مجموعه‌ای از متدها و ویژگی‌ها را روی اشیای req و res ارائه می‌دهد. این متدها از طریق prototype به ارث می‌رسند و همین موضوع امکان بازنویسی آن‌ها را فراهم می‌کند.

دو نقطهٔ اصلی برای گسترش API وجود دارد:

  • سطح جهانی: express.request و express.response
  • سطح برنامه: app.request و app.response

تغییر در سطح جهانی روی تمام برنامه‌های Express در همان پروسه اثر می‌گذارد. اما تغییر در سطح برنامه فقط روی همان app اعمال می‌شود.

2. بازنویسی متدها (Methods)


می‌توان رفتار متدهای موجود را با تعریف یک تابع جدید تغییر داد.

مثال: بازنویسی res.sendStatus

app.response.sendStatus = function (statusCode, type, message) {
  return this.contentType(type)
    .status(statusCode)
    .send(message)
}

این نسخهٔ جدید سه آرگومان می‌گیرد و پیام سفارشی ارسال می‌کند:

res.sendStatus(404, 'application/json', '{"error":"resource not found"}')

3. بازنویسی ویژگی‌ها (Properties)


ویژگی‌های Express دو نوع هستند:

  • ویژگی‌های اختصاص داده‌شده: مانند req.baseUrl — قابل بازنویسی نیستند.
  • ویژگی‌های getter: مانند req.ip — قابل بازنویسی هستند.

مثال: بازنویسی req.ip

Object.defineProperty(app.request, 'ip', {
  configurable: true,
  enumerable: true,
  get () { return this.get('Client-IP') }
})

اکنون مقدار IP از هدر Client-IP خوانده می‌شود.

4. تغییر Prototype


Express برای ساخت req و res از prototypeهای زیر استفاده می‌کند:

  • http.IncomingRequest.prototype
  • http.ServerResponse.prototype

در صورت نیاز می‌توان این prototypeها را تغییر داد، اما بهتر است فقط در سطح برنامه انجام شود.

مثال:

Object.setPrototypeOf(Object.getPrototypeOf(app.request), FakeRequest.prototype)
Object.setPrototypeOf(Object.getPrototypeOf(app.response), FakeResponse.prototype)

5. استفاده از Template Engine در Express


Template Engineها امکان استفاده از فایل‌های قالب را فراهم می‌کنند. در زمان اجرا، مقادیر پویا جایگزین متغیرهای قالب شده و خروجی HTML تولید می‌شود.

Express از Template Engineهای مختلفی پشتیبانی می‌کند:

  • Pug (پیش‌فرض)
  • EJS
  • Handlebars
  • و سایر Engineها از طریق کتابخانهٔ consolidate

6. تنظیم Template Engine


در فایل app.js تنظیمات زیر را انجام دهید:

app.set('views', './views')
app.set('view engine', 'pug')

نصب Pug:

npm install pug --save

7. ساخت فایل قالب (Pug)


فایل views/index.pug:

html
  head
    title= title
  body
    h1= message

8. رندر کردن قالب


app.get('/', (req, res) => {
  res.render('index', { title: 'Hey', message: 'Hello there!' })
})

درخواست به صفحهٔ اصلی باعث رندر شدن قالب و ارسال HTML می‌شود.

9. نکته دربارهٔ Cache


Cache فقط خود قالب را ذخیره می‌کند، نه خروجی HTML را. بنابراین در هر درخواست، قالب دوباره رندر می‌شود.

نتیجه‌گیری


Express انعطاف‌پذیری بسیار بالایی دارد. با بازنویسی API می‌توان رفتار req و res را سفارشی کرد و با Template Engineها می‌توان صفحات HTML پویا ساخت. ترکیب این دو قابلیت، Express را به ابزاری قدرتمند برای ساخت برنامه‌های وب مدرن تبدیل می‌کند.

نوشته و پژوهش شده توسط دکتر شاهین صیامی