Пошук уроків, статей та іншого контенту
Створите DTO для опису структури тіла запиту та використаєте їх у методах контролера.
Клієнт може передати дані на сервер у тілі HTTP-запиту. Наприклад, під час створення користувача тіло запиту може мати такий вигляд:
{
"name": "Олена",
"email": "olena@example.com"
}У NestJS тіло запиту доступне в методі контролера через декоратор
@Body()Без DTO можна отримати тіло як звичайний об’єкт:
@Post()
create(@Body() body: any) {
return body;
}Такий підхід не описує, які саме поля очікує сервер. Для цього використовують DTO.
DTO, або Data Transfer Object, — це об’єкт для опису даних, які передаються між частинами програми.
У NestJS DTO зазвичай створюють як TypeScript-клас:
export class CreateCatDto {
name: string;
age: number;
}Цей клас описує, що для створення кота очікуються:
name типу string;
age типу number.
DTO допомагає:
зрозуміти структуру тіла запиту;
отримати підказки TypeScript у редакторі;
уникати використання any;
передавати в метод контролера об’єкт із передбачуваною структурою.
DTO не створює нову таблицю в базі даних і не є моделлю бази даних. Його завдання — описати дані запиту.
Створимо файл create-cat.dto.ts:
export class CreateCatDto {
name: string;
age: number;
}Назва DTO часто складається з назви операції та суфікса Dto:
CreateCatDto — дані для створення;
UpdateCatDto — дані для оновлення;
LoginDto — дані для входу.
DTO можна зберігати в окремій папці dto:
src/
├── cats/
│ ├── dto/
│ │ └── create-cat.dto.ts
│ └── cats.controller.tsДля отримання тіла запиту використовується @Body():
@Post()
create(@Body() createCatDto: CreateCatDto) {
return createCatDto;
}Тут:
@Body() отримує тіло HTTP-запиту;
createCatDto — локальна змінна з даними;
CreateCatDto — тип змінної.
Повний приклад контролера:
import { Body, Controller, Post } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
@Controller('cats')
export class CatsController {
@Post()
create(@Body() createCatDto: CreateCatDto) {
return {
message: 'Кота створено',
cat: createCatDto,
};
}
}Тепер клієнт може надіслати POST-запит на /cats із таким тілом:
{
"name": "Мурчик",
"age": 3
}Відповідь контролера буде приблизно такою:
{
"message": "Кота створено",
"cat": {
"name": "Мурчик",
"age": 3
}
}Файл src/cats/dto/create-cat.dto.ts:
export class CreateCatDto {
name: string;
age: number;
}Файл src/cats/cats.controller.ts:
import { Body, Controller, Post } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
@Controller('cats')
export class CatsController {
@Post()
create(@Body() createCatDto: CreateCatDto) {
return {
message: 'Кота створено',
cat: createCatDto,
};
}
}Файл src/cats/cats.module.ts:
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
@Module({
controllers: [CatsController],
})
export class CatsModule {}Підключіть модуль у app.module.ts:
import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule {}Після запуску застосунку можна надіслати запит:
curl -X POST http://localhost:3000/cats \
-H "Content-Type: application/json" \
-d '{"name":"Мурчик","age":3}'Декоратор @Body() можна використати для отримання всього тіла або лише одного поля.
Щоб отримати лише поле name, передайте його назву в @Body():
@Post()
create(@Body('name') name: string) {
return {
name,
};
}Для тіла:
{
"name": "Мурчик",
"age": 3
}метод отримає значення "Мурчик".
Однак для кількох пов’язаних полів зручніше використовувати DTO:
@Post()
create(@Body() createCatDto: CreateCatDto) {
return createCatDto;
}Так структура запиту описана в одному місці.
TypeScript-типи існують під час розробки й компіляції, але не виконують автоматичну перевірку тіла HTTP-запиту під час роботи застосунку.
Наприклад, такий запит формально може дійти до контролера:
{
"name": 123,
"age": "три"
}Сам запис:
create(@Body() createCatDto: CreateCatDto)не гарантує, що клієнт справді передав правильні типи.
DTO описує очікувану структуру для розробника та TypeScript. Для перевірки вхідних даних у NestJS додатково використовують validation-декоратори та ValidationPipe. Це окремий крок після створення DTO.
any@Post()
create(@Body() body: any) {
return body;
}any вимикає перевірку типів і приховує структуру запиту. Краще створити DTO:
@Post()
create(@Body() createCatDto: CreateCatDto) {
return createCatDto;
}Інтерфейс добре описує типи під час компіляції:
interface CreateCat {
name: string;
age: number;
}Але інтерфейси TypeScript видаляються після компіляції. У NestJS DTO зазвичай створюють як класи, оскільки класи можуть бути доступні під час виконання програми та використовуватися разом із механізмами NestJS для перетворення і перевірки даних.
Content-TypeЯкщо тіло передається у форматі JSON, клієнт має вказати:
Content-Type: application/jsonБез цього сервер може некоректно обробити тіло запиту.
DTO:
export class CreateCatDto {
name: string;
age: number;
}Запит:
{
"catName": "Мурчик",
"years": 3
}У цьому випадку назви полів не відповідають DTO. Потрібно або виправити тіло запиту:
{
"name": "Мурчик",
"age": 3
}або змінити структуру DTO.
DTO лише описує дані запиту. Він не зберігає дані в базу даних і не створює сутність. Для цього контролер має передати DTO в сервіс, який виконає потрібну бізнес-логіку.
Тіло HTTP-запиту отримують через декоратор @Body().
DTO — це клас, який описує структуру тіла запиту.
DTO використовують як тип параметра методу контролера.
Для одного поля можна використовувати @Body('fieldName').
Для кількох полів краще створити окремий DTO.
DTO покращує читабельність і підказки TypeScript, але саме по собі не перевіряє дані під час виконання.
Для JSON-запиту потрібно передавати заголовок Content-Type: application/json.