Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Request Lifecycle w NestJS - droga depeszy przez imperium

Architekcie imperium! Architekt Vitruvius, mistrz budowli i systemow, przygotowal dla Ciebie najwazniejsza lekcje tego modulu. Poznales juz middleware, guardy, interceptory, pipes, custom decorators i exception filters. Teraz czas zobaczyc, jak to WSZYSTKO laczy sie w jedna calosc - pelny cykl zycia zadania HTTP w NestJS!

Pelna droga depeszy przez imperium

Wyobraz sobie, ze depesza (request HTTP) wyrusza z dalekiej prowincji do Cezara. Po drodze przechodzi przez wiele punktow kontrolnych. Oto dokladna kolejnosc:

1Przychodzace zadanie HTTP
2        |
3        v
4  1. MIDDLEWARE (Straznik bramy)
5        |
6        v
7  2. GUARDS (Kontrola uprawnien)
8        |
9        v
10  3. INTERCEPTORS - before (Kronikarz - poczatek)
11        |
12        v
13  4. PIPES (Kontrola jakosci danych)
14        |
15        v
16  5. ROUTE HANDLER (Cezar podejmuje decyzje)
17        |
18        v
19  6. INTERCEPTORS - after (Kronikarz - koniec)
20        |
21        v
22  7. EXCEPTION FILTERS (Trybunal - w razie bledu)
23        |
24        v
25  Odpowiedz HTTP

Kazdy etap w szczegolach

1. Middleware - straznik bramy

Middleware wykonuje sie PIERWSZY, zanim NestJS w ogole wie, ktora metoda kontrolera zostanie wywolana. Ma dostep do surowego obiektu Request i Response:

1// Middleware wykonuje sie jako PIERWSZY
2@Injectable()
3export class LoggerMiddleware implements NestMiddleware {
4  use(req: Request, res: Response, next: NextFunction) {
5    console.log('[1. MIDDLEWARE] Depesza dotarla do bramy');
6    console.log('Metoda: ' + req.method + ', Sciezka: ' + req.path);
7    next(); // Przekaz dalej
8  }
9}

2. Guards - kontrola uprawnien

Guards wykonuja sie PO middleware, ale PRZED interceptorami i pipe'ami. Ich jedynym zadaniem jest odpowiedziec na pytanie: "Czy ten request ma prawo kontynuowac?":

1// Guard wykonuje sie jako DRUGI
2@Injectable()
3export class AuthGuard implements CanActivate {
4  canActivate(context: ExecutionContext): boolean {
5    console.log('[2. GUARD] Sprawdzam uprawnienia legionisty');
6    const request = context.switchToHttp().getRequest();
7    return !!request.headers.authorization; // true = wpusc, false = zablokuj
8  }
9}

3. Interceptors (before) - kronikarz poczatek

Interceptory maja unikalna wlasciwosc - wykonuja sie dwukrotnie: raz PRZED handlerem i raz PO nim. Faza "before" to kod przed

next.handle()
:

1// Interceptor - faza BEFORE (trzeci krok)
2@Injectable()
3export class TimingInterceptor implements NestInterceptor {
4  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
5    const start = Date.now();
6    console.log('[3. INTERCEPTOR before] Kronikarz rozpoczyna zapis');
7
8    return next.handle().pipe(
9      // Ta czesc to faza AFTER (szosty krok)
10      tap(() => {
11        const duration = Date.now() - start;
12        console.log('[6. INTERCEPTOR after] Czas: ' + duration + 'ms');
13      }),
14    );
15  }
16}

4. Pipes - kontrola jakosci danych

Pipes wykonuja sie BEZPOSREDNIO przed handlerem. Transformuja i waliduja dane wejsciowe:

1// Pipe wykonuje sie jako CZWARTY
2@Injectable()
3export class ParseLegionIdPipe implements PipeTransform {
4  transform(value: any) {
5    console.log('[4. PIPE] Waliduje dane wejsciowe: ' + value);
6    const id = parseInt(value, 10);
7    if (isNaN(id)) {
8      throw new BadRequestException('ID musi byc liczba!');
9    }
10    return id;
11  }
12}

5. Route Handler - decyzja Cezara

Handler to docelowa metoda kontrolera - tutaj wykonuje sie logika biznesowa:

1@Controller('legiones')
2export class LegionController {
3  @Get(':id')
4  @UseGuards(AuthGuard)
5  @UseInterceptors(TimingInterceptor)
6  findLegion(@Param('id', ParseLegionIdPipe) id: number) {
7    console.log('[5. HANDLER] Cezar przetwarza zapytanie o legion ' + id);
8    return { id, name: 'Legio X Gemina', commander: 'Marcus' };
9  }
10}

6. Interceptors (after) - kronikarz koniec

Po zakonczeniu handlera, sterowanie wraca do interceptora - do kodu wewnatrz

pipe(tap(...))
. Tu mozesz transformowac odpowiedz, logowac czas, itp.

7. Exception Filters - trybunal

Exception Filters wykonuja sie TYLKO gdy zostanie rzucony wyjatek - na dowolnym etapie. Jesli guard rzuci ForbiddenException, filtr to przechwyci. Jesli pipe rzuci BadRequestException - tez:

1// Exception Filter - lapie bledy z KAZDEGO etapu
2@Catch(HttpException)
3export class ImperiumExceptionFilter implements ExceptionFilter {
4  catch(exception: HttpException, host: ArgumentsHost) {
5    console.log('[7. EXCEPTION FILTER] Trybunal obsluguje blad');
6    const ctx = host.switchToHttp();
7    const response = ctx.getResponse();
8    response.status(exception.getStatus()).json({
9      error: exception.message,
10      timestamp: new Date().toISOString(),
11    });
12  }
13}

Praktyczne implikacje kolejnosci

Zrozumienie kolejnosci jest kluczowe dla debugowania:

1// Przyklad: Co sie stanie gdy guard odrzuci request?
2// 1. Middleware - WYKONA SIE (logowanie)
3// 2. Guard - ODRZUCI (rzuci ForbiddenException)
4// 3. Interceptor before - NIE wykona sie
5// 4. Pipe - NIE wykona sie
6// 5. Handler - NIE wykona sie
7// 6. Interceptor after - NIE wykona sie
8// 7. Exception Filter - WYKONA SIE (obsluzy ForbiddenException)
9
10// Przyklad: Co sie stanie gdy pipe odrzuci dane?
11// 1. Middleware - WYKONA SIE
12// 2. Guard - WYKONA SIE (przepusci)
13// 3. Interceptor before - WYKONA SIE
14// 4. Pipe - ODRZUCI (rzuci BadRequestException)
15// 5. Handler - NIE wykona sie
16// 6. Interceptor after - NIE wykona sie (brak odpowiedzi)
17// 7. Exception Filter - WYKONA SIE (obsluzy BadRequestException)

Debugowanie pipeline'u

Praktyczna technika debugowania - dodaj logi na kazdym etapie:

1// middleware
2console.log('[MW] ' + req.method + ' ' + req.path);
3
4// guard
5console.log('[GUARD] User: ' + request.user?.name);
6
7// interceptor before
8console.log('[INT-B] Handler: ' + context.getHandler().name);
9
10// pipe
11console.log('[PIPE] Value: ' + value + ' -> ' + transformed);
12
13// handler
14console.log('[HANDLER] Processing...');
15
16// interceptor after
17console.log('[INT-A] Duration: ' + duration + 'ms');
18
19// exception filter
20console.log('[FILTER] Error: ' + exception.message);

Gdy zobaczysz logi, mozesz dokladnie sledzic droge requestu przez caly pipeline i szybko znalezc, na ktorym etapie wystepuje problem.

Podsumowanie cyklu zycia

Zapamietaj te kolejnosc jak maszerujaca kolumne legionu:

  1. Middleware - pierwszy punkt kontrolny (surowy request)
  2. Guards - kontrola uprawnien (wpuscic/nie wpuscic)
  3. Interceptors before - poczatek obserwacji
  4. Pipes - walidacja i transformacja danych
  5. Handler - logika biznesowa
  6. Interceptors after - koniec obserwacji, transformacja odpowiedzi
  7. Exception Filters - obsluga bledow (gdy cos poszlo nie tak)

Znajomosc tego cyklu to fundament kazdego zaawansowanego programisty NestJS - jak znajomosc strategii bitewnej dla centuriona!

Vai a CodeWorlds