Вопрос или проблема
Я создаю POST шлюз вот так:
@Controller('users')
@ApiTags('user')
export class UserController {
constructor(private readonly userService: UserService) {}
@Post('register')
@ApiBody({ type: NewUserInputDto })
registerUser(@Body() newUserInput: NewUserInputDto) {
return this.userService.registerUser(newUserInput);
}
}
Класс ‘NewUserInputDto’ выглядит так:
export class NewUserInputDto {
@ApiProperty()
fullName: string;
@ApiProperty()
phone: string;
@ApiProperty()
email: string;
@ApiProperty()
password: string;
@ApiProperty()
retypedPassword: string;
}
Когда я пытаюсь отправить запрос с телом, соответствующим DTO, я получаю эту ошибку (я изменил некоторые сообщения об исключениях, чтобы они были понятнее):
[Nest] 47901 - 09/23/2024, 10:49:05 AM ERROR [HttpExceptionFilter] Объект:
[
{
"target": {
"fullName": "string",
"phone": "string",
"email": "string",
"password": "string",
"retypedPassword": "string"
},
"value": "string",
"property": "fullName",
"constraints": {
"whitelistValidation": "свойство fullName не должно существовать"
}
},
{
"target": {
"fullName": "string",
"phone": "string",
"email": "string",
"password": "string",
"retypedPassword": "string"
},
"value": "string",
"property": "phone",
"constraints": {
"whitelistValidation": "свойство phone не должно существовать"
}
},
{
"target": {
"fullName": "string",
"phone": "string",
"email": "string",
"password": "string",
"retypedPassword": "string"
},
"value": "string",
"property": "email",
"constraints": {
"whitelistValidation": "свойство email не должно существовать"
}
},
{
"target": {
"fullName": "string",
"phone": "string",
"email": "string",
"password": "string",
"retypedPassword": "string"
},
"value": "string",
"property": "password",
"constraints": {
"whitelistValidation": "свойство password не должно существовать"
}
},
{
"target": {
"fullName": "string",
"phone": "string",
"email": "string",
"password": "string",
"retypedPassword": "string"
},
"value": "string",
"property": "retypedPassword",
"constraints": {
"whitelistValidation": "свойство retypedPassword не должно существовать"
}
}
]
[Nest] 47901 - 09/23/2024, 10:49:05 AM ERROR [HttpExceptionFilter] свойство fullName не должно существовать
UnprocessableEntityException: Исключение о невозможности обработки сущности
at ValidationPipe.exceptionFactory (/home/long/vegeta/HealthyFoodApplication_BackEnd/src/main.ts:74:16)
at ValidationPipe.transform (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/@nestjs/common/pipes/validation.pipe.js:72:30)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at resolveParamValue (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/@nestjs/core/router/router-execution-context.js:147:23)
at async Promise.all (index 0)
at pipesFn (/home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/@nestjs/core/router/router-execution-context.js:150:13)
at /home/long/vegeta/HealthyFoodApplication_BackEnd/node_modules/@nestjs/core/router/router-execution-context.js:37:30
POST /api/v1/users/register 422 115 - 10.342 ms
В чем может быть проблема?
Я попробовал удалить ограничение типа данных (которое выглядит так registerUser(@Body() newUserInput)
), и все работает нормально. Я также писал другие шлюзы аналогичным образом, и они работают без проблем.
Ответ или решение
Ошибка UnprocessableEntityException
, с которой вы столкнулись, возникает при попытке валидации входящих данных, которые не соответствуют ожиданиям вашего DTO. В вашем случае проблема связана с настройками валидации, применяемыми к классам DTO в NestJS.
-
Проверка DTO: Убедитесь, что ваш класс
NewUserInputDto
правильно настроен. В вашем коде все выглядит корректно с точки зрения определения DTO, но необходимо проверить, не пропущены ли аннотации, касающиеся валидации.Если вы еще не сделали этого, добавьте аннотации для валидации из библиотеки
class-validator
.Пример для вашего DTO:
import { IsEmail, IsNotEmpty, IsPhoneNumber, IsString, MinLength } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class NewUserInputDto { @ApiProperty() @IsString() @IsNotEmpty() fullName: string; @ApiProperty() @IsPhoneNumber(null) // На всякий случай, вы можете указать страну @IsNotEmpty() phone: string; @ApiProperty() @IsEmail() @IsNotEmpty() email: string; @ApiProperty() @IsString() @IsNotEmpty() @MinLength(6) // Минимальная длина пароля password: string; @ApiProperty() @IsString() @IsNotEmpty() @MinLength(6) // Минимальная длина повторного пароля retypedPassword: string; }
-
Включение валидации: Убедитесь, что вы включили валидацию в вашем приложении NestJS. Обычно это делается в главном файле приложения (например,
main.ts
). Вот как это можно сделать:import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true })); await app.listen(3000); } bootstrap();
Параметры
whitelist
иforbidNonWhitelisted
помогут Вам предотвратить отправку данных, не определённых в DTO, и будут работать на генерацию ошибок валидации, если клиент попытается отправить дополнительные поля. -
Проверка данных запроса: При отправке запроса убедитесь, что вы присылаете данные именно в том формате, который ожидается. Пример правильного тела запроса для вашего контроллера:
{ "fullName": "Иван Иванов", "phone": "+79991234567", "email": "ivan@example.com", "password": "securePassword", "retypedPassword": "securePassword" }
Если вы выполните все вышеперечисленные шаги, то проблема с UnprocessableEntityException
должна быть устранена. Если ошибка по-прежнему появляется, проверьте логи и данные запроса, чтобы убедиться, что они соответствуют ожидаемым типам данных.