Routing va DTO
Har qanday REST API'ning yuragi โ bu routing, ya'ni turli manzil va HTTP metodlarini tegishli funksiyalarga bog'lash. NestJS routing'ni juda tushunarli qiladi: har bir metod uchun alohida dekorator, parametrlarni olish uchun alohida dekorator. Bundan tashqari, kiruvchi ma'lumotni DTO klasslari va avtomatik validatsiya bilan xavfsiz qilishni o'rganamiz.
HTTP metod dekoratorlari
REST API'da har bir amal o'z HTTP metodiga ega bo'ladi. NestJS har bir metod uchun dekorator beradi. Ular controller metodini ma'lum bir marshrut va metodga bog'laydi:
@Get()โ ma'lumot o'qish (masalan, ro'yxatni olish);@Post()โ yangi ma'lumot yaratish;@Put()โ mavjud ma'lumotni to'liq yangilash;@Patch()โ ma'lumotning bir qismini yangilash;@Delete()โ ma'lumotni o'chirish.
// src/users/users.controller.ts
import { Controller, Get, Post, Put, Delete } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get() // GET /users
findAll() { return 'ro'yxat'; }
@Post() // POST /users
create() { return 'yaratildi'; }
@Put(':id') // PUT /users/5
update() { return 'yangilandi'; }
@Delete(':id') // DELETE /users/5
remove() { return 'o'chirildi'; }
}
@Controller('users')) va metod yo'li (@Get(':id')) birlashadi. Ya'ni @Get(':id') aslida GET /users/:id manzilini bildiradi.@Param โ marshrut parametrlari
Marshrutda :id kabi qism marshrut parametri deb ataladi. Uning qiymatini olish uchun @Param dekoratoridan foydalanamiz. Masalan, GET /users/42 so'rovida id qiymati 42 bo'ladi:
import { Controller, Get, Param } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get(':id')
findOne(@Param('id') id: string) {
// Diqqat: parametr doim satr (string) sifatida keladi
return 'Foydalanuvchi ID: ' + id;
}
}
id'ni son sifatida ishlatish uchun uni Number(id) bilan aylantiring yoki keyinroq ko'radigan ParseIntPipe'dan foydalaning.@Query โ so'rov parametrlari
URL'dagi ? dan keyingi qism โ bu query string (so'rov parametrlari). Masalan /users?page=2&limit=10. Ularni @Query dekoratori bilan olamiz. Bu odatda filtrlash, saralash va sahifalash uchun ishlatiladi:
import { Controller, Get, Query } from '@nestjs/common';
@Controller('users')
export class UsersController {
// GET /users?page=2&limit=10
@Get()
findAll(@Query('page') page: string, @Query('limit') limit: string) {
return 'Sahifa: ' + page + ', limit: ' + limit;
}
}
@Body โ so'rov tanasi
POST va PUT so'rovlarida ma'lumot odatda so'rov tanasida (body) JSON ko'rinishida yuboriladi. Uni olish uchun @Body dekoratoridan foydalanamiz. NestJS JSON'ni avtomatik o'qiydi (Express'dagi express.json() ichkarida allaqachon yoqilgan):
import { Controller, Post, Body } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Post()
create(@Body() body: any) {
// body โ bu mijoz yuborgan JSON obyekti
return 'Yaratildi: ' + body.ism;
}
}
Lekin body: any yozish yomon amaliyot: bu tipni yo'qotadi va ma'lumot shaklini nazorat qilmaydi. Aynan shu yerda DTO tushunchasi kirib keladi.
DTO โ ma'lumot uzatish obyekti
DTO (Data Transfer Object โ ma'lumot uzatish obyekti) โ bu so'rov tanasi qanday ko'rinishda bo'lishini belgilaydigan klass. U ma'lumotning shaklini (qaysi maydonlar, qaysi tiplar) rasmiylashtiradi. DTO odatda alohida faylda yoziladi:
// src/users/dto/create-user.dto.ts
export class CreateUserDto {
ism: string;
email: string;
yosh: number;
}
Endi controller'da any o'rniga DTO tipini ishlatamiz. Bu tahrirlovchida avtomatik to'ldirish (autocomplete) va tip xavfsizligini beradi:
import { Controller, Post, Body } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
@Controller('users')
export class UsersController {
@Post()
create(@Body() createUserDto: CreateUserDto) {
// Endi createUserDto.ism, .email, .yosh tip bilan mavjud
return 'Yaratildi: ' + createUserDto.ism;
}
}
interface orasidagi farq muhim: DTO klass bo'lishi kerak, interface emas. Sababi โ validatsiya dekoratorlari (keyingi bo'lim) faqat klasslarda ishlaydi. TypeScript interface'lari kompilyatsiya vaqtida yo'qoladi, klasslar esa ishga tushish paytida ham mavjud bo'ladi.class-validator bilan validatsiya
DTO'ning eng katta kuchi โ u avtomatik validatsiyaga imkon beradi. Buning uchun ikki paket kerak: class-validator va class-transformer. Ularni o'rnatamiz:
npm install class-validator class-transformer
Endi DTO maydonlariga validatsiya dekoratorlarini qo'shamiz. Har bir dekorator ma'lum bir qoidani tekshiradi:
// src/users/dto/create-user.dto.ts
import { IsString, IsEmail, IsInt, Min, Max, MinLength } from 'class-validator';
export class CreateUserDto {
@IsString()
@MinLength(2, { message: 'Ism kamida 2 harf bo'lsin' })
ism: string;
@IsEmail({}, { message: 'Email formati noto'g'ri' })
email: string;
@IsInt()
@Min(18)
@Max(120)
yosh: number;
}
Ko'p ishlatiladigan validatsiya dekoratorlari:
@IsString(),@IsInt(),@IsBoolean()โ tip tekshiruvi;@IsEmail(),@IsUrl()โ format tekshiruvi;@MinLength(n),@MaxLength(n)โ satr uzunligi;@Min(n),@Max(n)โ sonlar chegarasi;@IsOptional()โ maydon ixtiyoriy ekanligini bildiradi;@IsNotEmpty()โ bo'sh bo'lmasligi kerak.
ValidationPipe โ validatsiyani yoqish
Dekoratorlarni yozishning o'zi yetarli emas โ NestJS'ga ularni tekshirishni buyurish kerak. Buni ValidationPipe global tarzda yoqib qilamiz. Buni main.ts'da bir marta sozlaymiz:
// src/main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Global validatsiyani yoqamiz:
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // DTO'da yo'q maydonlarni tashlab yuborish
forbidNonWhitelisted: true, // Ortiqcha maydon bo'lsa xato berish
transform: true, // Kelgan ma'lumotni DTO tipiga aylantirish
}));
await app.listen(3000);
}
bootstrap();
Endi agar mijoz noto'g'ri ma'lumot yuborsa (masalan, yosh o'rniga 15 yoki email o'rniga axlat), NestJS avtomatik 400 Bad Request xatosini qaytaradi. Siz controller'da hech qanday if tekshiruvi yozishingiz shart emas:
// Mijoz shu ma'lumotni yuborsa:
// { "ism": "A", "email": "xato", "yosh": 15 }
// NestJS avtomatik 400 xato qaytaradi:
// {
// "statusCode": 400,
// "message": [
// "Ism kamida 2 harf bo'lsin",
// "Email formati noto'g'ri",
// "yosh must not be less than 18"
// ],
// "error": "Bad Request"
// }
whitelist: true juda foydali xavfsizlik sozlamasi: u DTO'da e'lon qilinmagan barcha maydonlarni avtomatik olib tashlaydi. Bu mijoz ortiqcha maydonlar (masalan, isAdmin: true) yuborib, tizimni chalg'itishining oldini oladi.ParseIntPipe โ parametr aylantirish
Yodingizda bo'lsa, marshrut parametrlari doim satr keladi. NestJS'ning tayyor Pipe'lari qiymatni avtomatik aylantirib, tekshirib beradi. Masalan ParseIntPipe satrni songa aylantiradi va agar bu mumkin bo'lmasa, 400 xato beradi:
import { Controller, Get, Param, ParseIntPipe } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
// id endi haqiqiy son (number), aylantirish shart emas
// Agar /users/abc so'ralsa, avtomatik 400 xato qaytadi
return 'ID: ' + id;
}
}
Xulosa
- HTTP metodlari uchun
@Get,@Post,@Put,@Patch,@Deletedekoratorlari mavjud; @Parammarshrut parametrini,@Queryso'rov parametrini,@Bodyso'rov tanasini oladi;- DTO โ so'rov tanasi shaklini belgilaydigan klass (interface emas);
class-validatordekoratorlari (@IsString,@IsEmail,@Min) validatsiya qoidalarini beradi;- ValidationPipe global yoqilganda ma'lumotni avtomatik tekshiradi va noto'g'ri bo'lsa 400 qaytaradi;
whitelist: trueortiqcha maydonlarni olib tashlab, xavfsizlikni oshiradi;ParseIntPipekabi pipe'lar parametrlarni avtomatik aylantirib tekshiradi.