Šta su kontroleri?
Kontroleri u Nest.js su klasične TypeScript klase koje su dekorisane @Controller() dekoratorom. U ovakvim klasama se definišu metode koji odgovaraju HTTP operacijama kao što su GET, POST, PUT, DELETE, gde je svaki metod u okviru kontrolera dekorisan odgovarajućim HTTP dekoratorom.
Primer jednostavnog kontrolera:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { Controller, Get, Post, Body, Param } from '@nestjs/common'; @Controller('users') export class UsersController { private users = []; @Get() findAll(): any[] { return this.users; } @Get(':id') findOne(@Param('id') id: string): any { return this.users.find(user => user.id === id); } @Post() create(@Body() user: any): string { this.users.push(user); return 'User created successfully'; } } |
U ovom primeru @Controller('users') dekorator definiše osnovnu rutu (“/users“) za sve metode unutar kontrolera. Ovaj kontroler iz primera ima tri metode za tri tipa zahteva, i sve tri metode su obeležene sa odgovajućim dekoratorima u zavisnosti od tipa HTTP zahteva koji obrađuju:
- findAll(): Obradjuje GET zahtev na ruti /users i vraća listu svih korisnika.
- findOne(): Obradjuje GET zahtev na ruti /users/:id i vraća korisnika sa zadatim ID-om.
- create(): Obradjuje POST zahtev na ruti /users i kreira novog korisnika.
Kreiranje kontrolera
Da biste dodali kontroler u modul, najlakše je koristiti sledeće komande u terminalu:
1 |
nest generate controller users |
Ova komanda će generisati users.controller.ts fajl u okviru novog foldera “users” i njega će smestiti u root projekta tj. src/users:
1 2 3 4 |
import { Controller } from '@nestjs/common'; @Controller('users') export class UsersController {} |
Ako ne postoji direktorijum pod nazivom “users” ova komanda će i njega napraviti. Ukoliko ipak ne želimo da napravimo folder pod nazivom kontrolera već samo kontroler fajl, onda koristimo flag --flat.
1 |
nest generate controller nekiKontroler --flat |
Prethodna naredba će napraviti u root direktorijumu (“src”) samo fajl vezan za kontroler nekiKontroler.controller.ts, takodje postoji način da kreiramo novi kontroler fajl u već postojeći folder, a za to koristimo sledeću sintaksu:
1 |
nest generate controller nekiFolder/noviKontroler --flat |
Sa ovom naredbom će biti kreiran fajl “noviKontroler.controller.ts” u okviru foldera pod nazivom “nekiFolder”.
Naredba će pored toga će istovremeno dodati taj kontroler i u modul u okviru liste svih kontrolera:
1 2 3 4 5 6 7 8 9 10 11 |
import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { UsersController } from './cats/Users.controller'; @Module({ imports: [], controllers: [AppController, UsersController], providers: [AppService], }) export class AppModule {} |
Dekoratori za pristup podacima request-a
Pored dekoratora za obeležavanje tipa request-a (@Get(), @Post()…), postoje i dekoratori za lakši pristup podacima zahteva. Ovi dekoratori olakšavaju rad sa različitim delovima HTTP zahteva i omogućavaju jednostavno i čitljivo rukovanje zahtevima unutar kontrolera:
- @Param('id'): Omogućava pristup parametru id iz URL-a
- @Body(): Omogućava pristup telu POST zahteva.
- @Headers() omogućava pristup HTTP zaglavljima.
- @Ip() omogućava pristup IP adresi klijenta.
- @Body() omogućava pristup telu POST zahteva.
- @Session() omogućava pristup sesijskim podacima.
- @Cookies() omogućava pristup kolačićima.
- @HostParam('host') omogućava pristup parametrima hosta.
Primer
Evo kako možete koristiti neke od ovih dekoratora u kontroleru:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
import { Controller, Get, Post, Body, Param, Query, Headers, Session, Ip, HostParam } from '@nestjs/common'; @Controller('example') export class ExampleController { //URL: http://localhost:3000/example/123?search=test @Get(':id') findOne( @Param('id') id: string, @Query() query: any, @Ip() ip: string ): string { console.log('Query:', query); // Query: { search: 'test' } console.log('IP Address:', ip); // IP Address: 127.0.0.1 return `User with id ${id}`; // User with id 123 } // URL: http://localhost:3000/example @Post() create( @Body() body: any, @Session() session: any, @Cookies() cookies: any): string { console.log('Body:', body); // Body: { name: 'John Doe' } console.log('Session:', session); // Session: { ... } // sesijski podaci, ako su prisutni console.log('Cookies:', cookies); // Cookies: { ... } // podaci iz kolačića, ako su prisutni return 'User created successfully'; } // URL: http://subdomain.example.com:3000/example @Get() findWithHostParam( @HostParam('host') host: string): string { console.log('Host:', host); // Host: subdomain.example.com return `Host is ${host}`; } } |
U prethodnom primeru dekorator @Get označava da će metoda findOne() odgovoriti na zahtev. Dekorator @Param(‘id’) izvlači parametar pod imenom “id” iz URL-a zahteva, dok dekorator @Query() izvlači sve query parametre iz URL-a zahteva i čuva ih u objektu “query” (npr. za URL /users/123?search=test, query će biti { search: ‘test’ }). Dekorator @Ip() obezbedjuje IP adresu klijenta koji je poslao zahtev.
Dostupnost servisa u kontrolerima
Servisi se koriste za enkapsulaciju poslovne logike i omogućavaju ponovnu upotrebu koda. Servisi se mogu lako uvesti u kontrolere korišćenjem mehanizma za injekciju zavisnosti (dependency injection) koji pruža Nest.js. U Nest.js postoji nekoliko načina za injekciju servisa u kontroler.
Injectovanje servisa kroz konstruktor
Najčešći način je putem konstruktora, kao što je prikazano u sledećem primeru:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { Controller, Get, Post, Body, Param } from '@nestjs/common'; import { UsersService } from './users.service'; @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {} @Get() findAll(): any[] { return this.usersService.findAll(); } @Get(':id') findOne(@Param('id') id: string): any { return this.usersService.findOne(id); } @Post() create(@Body() user: any): string { return this.usersService.create(user); } } |
U ovom primeru, UsersController koristi UsersService za obradu zahteva. Servis se ubacuje u kontroler kroz konstruktor.
Injektovanje servisa kroz svojstvo
Iako nije toliko često korišćena, moguća je i injekcija servisa putem svojstava koristeći dekorator @Inject.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import { Controller, Get, Post, Body, Param, Inject } from '@nestjs/common'; import { UsersService } from './users.service'; @Controller('users') export class UsersController { @Inject(UsersService) private readonly usersService: UsersService; @Get() findAll(): any[] { return this.usersService.findAll(); } @Get(':id') findOne(@Param('id') id: string): any { return this.usersService.findOne(id); } @Post() create(@Body() user: any): string { return this.usersService.create(user); } } |
NAPOMENA:
Takodje postoji i “Manuelna injekcija” servisa ali je prilično komplikovana a koristi se samo u specifičnim slučajevima kada ne možete koristiti konstruktorsku ili property-based injekciju. Ovaj pristup koristi ModuleRef, koji omogućava pristup Nest.js Dependency Injection (DI) kontejneru za ručno dobijanje instanci servisa.