کاربرد Interceptor ها در NestJS

مقدمه
در توسعه برنامههای تحت وب با استفاده از فریمورک NestJS، یکی از مفاهیم کلیدی که قدرت و انعطافپذیری بالایی به برنامه میدهد، Interceptorها هستند. این ابزارها به شما اجازه میدهند قبل یا بعد از اجرای منطق درخواست، عملیات خاصی را انجام دهید. در این مقاله قصد داریم به صورت کامل با کاربرد Interceptorها در NestJS آشنا شویم و ببینیم چگونه میتوان از آنها برای بهبود عملکرد، امنیت و ساختار کد استفاده کرد.
کاربرد Interceptor در NestJS چیست؟
در NestJS، یک Interceptor نوعی middleware پیشرفته است که در سطح کنترلکنندهها یا متدها اجرا میشود. برخلاف middlewareهای سنتی، Interceptorها توانایی دارند هم قبل و هم بعد از اجرای handler اصلی عمل کنند. این ویژگی باعث میشود برای مواردی مانند لاگگیری، کش کردن پاسخها، تغییر ساختار دادهها، مدیریت خطاها و غیره بسیار مفید باشند.
معماری Interceptor در NestJS
Interceptorها در NestJS بر پایه RxJS Observables کار میکنند. آنها میتوانند درخواست ورودی را بررسی کرده و خروجی نهایی را پیش از ارسال به کلاینت تغییر دهند. در واقع، Interceptorها بین مرحله ارسال درخواست و دریافت پاسخ عمل میکنند.
[code language=”javascript”]
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log('Before handler execution');
const now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`After… ${Date.now() – now}ms`)),
);
}
}
[/code]
در کد بالا، قبل و بعد از اجرای handler، لاگهایی چاپ میشوند که برای پایش عملکرد مفید هستند.
کاربردهای رایج Interceptor ها
در ادامه به چند مورد از مهمترین کاربردهای Interceptorها در پروژههای NestJS اشاره میکنیم:
1. لاگگیری و مانیتورینگ (Logging & Monitoring)
Interceptorها میتوانند زمان اجرای متدها را ثبت کرده یا اطلاعات مربوط به ورودی و خروجیها را لاگ کنند. این قابلیت برای دیباگ کردن و تحلیل رفتار کاربران بسیار مفید است.
2. کش کردن دادهها (Caching)
با کمک Interceptorها میتوان خروجی برخی متدها را در حافظه یا یک سرویس کش مثل Redis ذخیره کرد تا در درخواستهای بعدی نیازی به اجرای مجدد منطق نباشد.
3. تغییر ساختار پاسخ (Response Mapping)
گاهی نیاز است خروجیها قبل از ارسال به کلاینت، ساختار خاصی داشته باشند. مثلا همه پاسخها دارای کلیدهای status
, data
, message
باشند. Interceptorها به راحتی این نیاز را برآورده میکنند.
4. مدیریت خطاها (Error Handling)
گرچه NestJS از Exception Filter استفاده میکند، اما Interceptorها نیز میتوانند در تغییر و کنترل رفتار خطاها نقش داشته باشند. مثلا میتوانید خطاهای خاصی را لاگ کرده یا فرمت آنها را تغییر دهید.
5. تبدیل دادههای ورودی و خروجی (Transformations)
میتوان خروجی متدها را به صورت پویا تغییر داد. مثلا رمز عبور را از پاسخ حذف کرد یا فیلدهای اضافی را پاک نمود.
چطور یک Interceptor بسازیم؟
ساخت یک Interceptor در NestJS ساده است. کافی است یک کلاس بسازید که NestInterceptor
را پیادهسازی کند و از متد intercept
استفاده نمایید.
[code language=”javascript”]
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
return next.handle().pipe(
map(data => ({
status: 'success',
data,
timestamp: new Date().toISOString(),
})),
);
}
}
[/code]
در مثال بالا، خروجی تمام متدهای کنترلر دارای ساختار یکسانی میشود که برای کلاینت بسیار خوانا است.
نحوه استفاده از Interceptor
برای اعمال یک Interceptor، سه روش وجود دارد:
1. در سطح متد
[code language=”javascript”]
<code class="whitespace-pre! language-ts"><span class="hljs-meta">@UseInterceptors</span>(<span class="hljs-title class_">LoggingInterceptor</span>)
<span class="hljs-meta">@Get</span>()
<span class="hljs-title function_">findAll</span>() {<span class="hljs-keyword">return</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">usersService</span>.<span class="hljs-title function_">findAll</span>();}
</code>[/code]
2. در سطح کنترلر
[code language=”javascript”]
@UseInterceptors(CacheInterceptor)
@Controller('products')
export class ProductsController { }
[/code]
3. در سطح سراسری (Global Interceptor)
[code language=”javascript”]
<code class="whitespace-pre! language-ts">app.<span class="hljs-title function_">useGlobalInterceptors</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">LoggingInterceptor</span>());</code> [/code]
با این روشها میتوان کنترل دقیقی روی محل اجرای Interceptor داشت.
نکات مهم در کاربرد Interceptor ها در NestJS
-
از Interceptorها برای منطق تکراری استفاده کنید، نه منطق اصلی بیزینسی.
-
برای عملیات زمانبر مانند کش یا پردازش سنگین، حتما از async/await یا Observables استفاده کنید.
-
هنگام استفاده از چند Interceptor، ترتیب اجرای آنها اهمیت دارد. ابتدا Interceptorهای نزدیکتر به متد اجرا میشوند.
مزایای استفاده از Interceptor در NestJS
مزیت | توضیح |
---|---|
جداسازی منطق جانبی | از منطق اصلی جدا میماند و کد را تمیزتر میکند |
افزایش قابلیت تست | چون ساختار جداگانه دارد، میتوان آن را مستقل تست کرد |
استفاده مجدد | میتوان یک Interceptor را در چند کنترلر استفاده کرد |
تطبیق با معماری مدرن | کاملا با اصول SOLID و Clean Architecture هماهنگ است |
جمعبندی
Interceptorها در NestJS ابزاری قدرتمند برای کنترل جریان دادهها و رفتار برنامه در مراحل قبل و بعد از اجرای متدهای کنترلر هستند. با استفاده صحیح از آنها میتوان اپلیکیشنی ساخت که هم ساختار تمیزتری دارد و هم عملکرد بهتری. از لاگگیری و کشکردن تا تبدیل پاسخها و مدیریت خطا، همگی با کمک Interceptorها قابل پیادهسازیاند.
اگر در حال توسعه یک پروژه با NestJS هستید، پیشنهاد میکنیم حتما از Interceptorها بهره بگیرید تا هم کد تمیزتری داشته باشید و هم امکانات حرفهایتری به برنامه خود اضافه کنید.
برای اطلاعات بیشتر میتوانید به مستندات رسمی Interceptors in nest مراجعه نمایید
سوالات متداول (FAQ)
آیا Interceptorها جایگزین middleware هستند؟
خیر. Middleware قبل از رسیدن درخواست به کنترلر اجرا میشود، اما Interceptor بین کنترلر و پاسخ عمل میکند.
آیا میتوان چند Interceptor را با هم استفاده کرد؟
بله. NestJS به شما اجازه میدهد چند Interceptor را به صورت همزمان و با ترتیب مشخص اعمال کنید.
تفاوت Interceptor و Guard در چیست؟
Guardها برای بررسی دسترسی و اعتبارسنجی کاربران استفاده میشوند. اما Interceptorها برای پردازش دادهها و تغییر پاسخها کاربرد دارند.
دیدگاهتان را بنویسید