Menu
CoddyTech

מיירטים

חלק מהיחידה TypeScript ו-NestJS במסלול ה-Node.js של Coddy. שיעור 23 מתוך 24.

אתם רוצים שכל תשובה תציין כמה זמן ארך הדבר, בלי לגעת בכל מטפל בנפרד. מיירט עוטף את המטפל: קוד לפני next.handle() רץ לפניו, וקוד שפועל על מה ש-next.handle() מחזירה רץ אחריו.

intercept(context: ExecutionContext, next: CallHandler) {
    console.log('before');
    return next.handle().pipe(
        tap(() => console.log('after')),
    );
}

next.handle() מספקת את תוצאת המטפל כ-observable של RxJS, ערך שמגיע מאוחר יותר. .pipe(tap(...)) מריצה פונקציה כשהערך מגיע, לפני ש-Nest שולחת אותו; ל-pipe הזה אין קשר לצינורות האימות של Nest. שומרים רצים לפני כל מיירט, ולכן בקשה ששומר מסרב לה לעולם לא מגיעה אליו. החזירו את ה-observable שעבר בצינור: Nest שולחת את מה שהוא מכיל. context.switchToHttp().getResponse() מספקת את res, שה-setHeader שלה מוסיפה כותרת.

app.useGlobalInterceptors(...) מחילה מיירט על כל הנתיבים; @UseInterceptors(...) מחילה אותו על בקר אחד.

challenge icon

אתגר

קל

הפקודה Run מפעילה שוב את המעקב שלך, באמצעות src/main.ts. קובצי התרגול הנפרדים יכולים להישאר בעץ; השרת הזה לא מפעיל אותם.

לקוחות וכלי הניטור שלך רוצים לדעת כמה זמן ארכה כל בקשה. הוסף כותרת תגובה, X-Response-Time, לכל תגובה מוצלחת, בלי לגעת באף נתיב.

  1. פתח את src/common/response-time.interceptor.ts. במתודה intercept של ResponseTimeInterceptor, תעד תחילה את השעה הנוכחית באמצעות Date.now(). קוד בראש intercept פועל לפני המתודה של הנתיב.
  2. קבל את res של Express באמצעות context.switchToHttp().getResponse().
  3. next.handle() מפעיל את המתודה של הנתיב ומחזיר את התוצאה שלה כ־observable של RxJS: ערך שמגיע מאוחר יותר. המשך להחזיר אותו, אבל העבר אותו דרך tap, שכבר יובא מ־rxjs, באמצעות המתודה .pipe() של ה־observable. הפונקציה שתעביר ל־tap פועלת כשהתוצאה מגיעה, לפני ש־Nest שולח אותה. בפונקציה הזאת, קרא ל־res.setHeader כדי להגדיר את X-Response-Time למספר האלפיות השנייה שחלפו מאז שתיעדת את השעה, ואחריו ms, למשל 3ms. (ל־.pipe() של RxJS אין קשר לצינורות האימות שבפרק 3. היא משרשרת שלב אל ה־observable.)
  4. ב־src/main.ts, רשום את המיירט לכל האפליקציה באמצעות app.useGlobalInterceptors(...), והעבר לו מופע חדש של ResponseTimeInterceptor, לצד הצינור והמסנן.
  5. גופי התגובות לא צריכים להשתנות. GET /tasks עדיין מחזיר { "items": [...], "page": 1, "total": 3, "pages": 2 }.

נסה זאת: שלח GET /tasks ופתח את לשונית Headers של התגובה. תראה את X-Response-Time עם ערך כמו 0ms או 2ms. גם ל־GET /stats יש אותו, וכך גם לבקשת POST עם { "title": "Buy milk" } שנשלחה עם הכותרת x-api-key: tasks-key-123. לאחר מכן שלח את בקשת ה־POST בלי המפתח: 403, וללא X-Response-Time. Nest מפעיל guards לפני מיירטים, ולכן ה־guard דחה את הבקשה לפני שהמיירט שלך התחיל לפעול. גם שגיאה שנזרקת בתוך נתיב מדלגת על הכותרת, מפני ש־tap פועל רק כשהתוצאה מגיעה.

נסו בעצמכם

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, tap } from 'rxjs';

@Injectable()
export class ResponseTimeInterceptor implements NestInterceptor {
    intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
        // רשמו את השעה, אפשרו ל-handler לפעול, ואז הגדירו את X-Response-Time.
        return next.handle();
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה TypeScript ו-NestJS

תרגלו בעצמכם: Express אונליין