Како користити Нест.јс филтере изузетака за руковање грешкама

U NestJS-u, filteri za izuzetke predstavljaju mehanizam za presretanje i upravljanje greškama na nivou cele aplikacije ili na specifičnom nivou kontrolera.

Oni vam omogućavaju da centralizujete logiku obrade grešaka, formatirate odgovore na greške i osigurate konzistentno rukovanje greškama u okviru vaše aplikacije. Detaljnije se upoznajte sa filterima izuzetaka i njihovom primenom za efikasno upravljanje greškama aplikacije.

Podrazumevano rukovanje greškama u NestJS-u

U NestJS-u, podrazumevani mehanizam za rukovanje greškama funkcioniše na način da preuzima sve izuzetke koje vaš kod aplikacije ne obradi.

Kada se u vašoj aplikaciji dogodi neobrađena greška, NestJS je hvata i klijentu šalje HTTP statusni kod 500, uz poruku o internoj serverskoj grešci. JSON odgovor koji NestJS vraća u ovim situacijama izgleda ovako:

 {
  "statusCode": 500,
  "message": "Internal server error"
}

Ukoliko objekat greške koji vaš kod generiše sadrži `statusCode` i `message` polja, NestJS će klijentu proslediti te vrednosti, umesto podrazumevanog odgovora.

Da biste izbegli ovaj opšti pristup i klijentu slali informativnije odgovore na greške, neophodno je da pažljivo upravljate svim potencijalnim greškama u vašoj aplikaciji. Ovo se može postići korišćenjem ugrađenih ili prilagođenih filtera izuzetaka koje NestJS nudi.

Kreiranje prilagođenog filtera izuzetaka

U cilju demonstracije procesa izrade prilagođenog filtera izuzetaka, kreiraćemo filter koji će obrađivati sve HTTP izuzetke.

Započnite kreiranjem datoteke pod nazivom `http.exception.ts` i dodajte sledeće uvoze:

 import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
} from '@nestjs/common';

import { Request, Response } from 'express';

Ovi uvozi imaju sledeću svrhu:

  • `ExceptionFilter`: Ovo je interfejs koji opisuje implementaciju filtera izuzetaka.
  • `Catch`: Ovo je dekorator koji označava klasu kao Nest filter izuzetaka.
  • `ArgumentsHost`: Ovaj interfejs pruža metode za preuzimanje argumenata prosleđenih rukovaocu. Omogućava vam da odaberete odgovarajući kontekst izvršavanja (npr. HTTP, RPC ili WebSockets) za preuzimanje argumenata.
  • `HttpException`: Ovo je klasa koja definiše osnovni Nest HTTP izuzetak.
  • `Request` i `Response`: Ovo su interfejsi za Express.js objekte zahteva i odgovora.

Nakon toga, kreirajte klasu `HttpExceptionFilter` koja implementira `ExceptionFilter`. Označite je dekoratorom `Catch` kako biste naznačili da obrađuje `HttpException`:

 @Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {}

Zatim, dodajte sledeći kod u ovu klasu:

 catch(exception: HttpException, host: ArgumentsHost) {
    
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    
    const request = ctx.getRequest<Request>();

    
    const status = exception.getStatus();

    
    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      path: request.url,
      message:
        exception.message
       || exception.getResponse()['message']
       || 'Internal Server Error',
    });
}

Ovaj blok koda preuzima objekte zahteva i odgovora iz `ArgumentsHost` objekta i izdvaja relevantne informacije iz izuzetka. Zatim vraća klijentu strukturirani JSON odgovor sa detaljima o grešci.

Povezivanje filtera izuzetaka

Filter izuzetaka možete primeniti na nivo kontrolera ili na nivou cele aplikacije, zavisno od vaših potreba.

Da biste globalno primenili filter izuzetaka, prvo ga uvezite u datoteku `main.ts`. Zatim, prosledite instancu vašeg filtera izuzetaka metodi `app.useGlobalFilters`:

 
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './exception/http.exception';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  
  app.useGlobalFilters(new HttpExceptionFilter());

  await app.listen(4050);
}

bootstrap();

Da biste filter izuzetaka povezali sa kontrolerom, uvezite dekorator `UseFilters` i filter izuzetaka. Označite svoju klasu kontrolera dekoratorom `@UseFilters` i prosledite instancu vašeg filtera izuzetaka kao argument dekoratoru:

 @Controller()
@UseFilters(new HttpExceptionFilter())
export class AppController {}

Mesto na kom povezujete filter će odrediti obim njegovog delovanja. Filteri povezani na kontroler će obrađivati greške samo za taj kontroler, dok će filteri primenjeni na nivou aplikacije obrađivati greške u celoj aplikaciji.

Korišćenje ugrađenih izuzetaka za generisanje grešaka

NestJS obezbeđuje set ugrađenih klasa izuzetaka koje možete koristiti za generisanje grešaka.

Na primer, grešku sa statusnim kodom 404 možete generisati pomoću klase `NotFoundException`:

   getUserById(id: number) {
    const user = users.find((user) => user.id === id);

    if (!user) {
      throw new NotFoundException({
        message: `User with id ${id} not found`,
      });
    }
  }

Ovaj blok koda proverava da li dati korisnik postoji. Ako ne postoji, generiše grešku 404 koristeći `NotFoundException`, uz poruku koja se prosleđuje kao argument.

Uobičajene ugrađene klase izuzetaka

Druge ugrađene klase izuzetaka uključuju, ali nisu ograničene na, sledeće:

  • `BadRequestException`: Generiše izuzetak koji ukazuje na loš zahtev sa statusnim kodom 400. Ovaj izuzetak možete koristiti kada je zahtev klijenta nevažeći ili pogrešno formatiran, i server ga ne može obraditi zbog greške klijenta. Ovo obično implicira da klijent treba da izmeni zahtev kako bi bio validan.
  • `UnauthorizedException`: Generiše izuzetak koji ukazuje na neovlašćen pristup sa statusnim kodom 401. Ovaj izuzetak možete koristiti kada korisnik nije autentifikovan ili nema potrebne dozvole za pristup resursu.
  • `ForbiddenException`: Generiše izuzetak koji ukazuje na zabranjen pristup sa statusnim kodom 403. Ovaj izuzetak možete koristiti kada je korisnik autentifikovan, ali nema ovlašćenje za izvršavanje određene radnje.
  • `RequestTimeoutException`: Generiše izuzetak koji ukazuje da je zahtev istekao sa statusnim kodom 408. Ovaj izuzetak možete koristiti kada server prekine zahtev zato što je za obradu trajalo predugo.
  • `ConflictException`: Generiše izuzetak koji ukazuje na konflikt sa statusnim kodom 409. Ovaj izuzetak možete koristiti kada postoji konflikt između zahteva klijenta i trenutnog stanja resursa, npr. kada pokušavate da kreirate resurs koji već postoji.
  • `InternalServerErrorException`: Generiše izuzetak koji ukazuje na internu serversku grešku sa statusnim kodom 500. Ovaj izuzetak možete koristiti kada dođe do neočekivane greške na strani servera, što ukazuje da server ne može da izvrši zahtev zbog internog problema.

Najbolje prakse za rukovanje greškama u NestJS-u

Prilikom rukovanja greškama u NestJS-u, obavezno koristite filtere izuzetaka kako biste globalno ili po kontroleru uhvatili i obradili izuzetke. Takođe, možete kreirati prilagođene filtere za specifične tipove izuzetaka.

Pored toga, uverite se da koristite odgovarajuće ugrađene klase izuzetaka kako biste generisali tačne i informativne poruke o greškama. Ovakav pristup značajno može poboljšati pouzdanost vaših NestJS aplikacija.