Можно ли проверить один параметр маршрута?
Допустим, у меня есть следующий маршрут:
companies/{companyId}/departments/{departmentId}/employees
Можно ли проверить оба идентификатора ресурса (companyId
, departmentId
) по отдельности? Я пытался следовать, но это не работает.
class ResourceId {
@IsNumberString()
@StringNumberRange(...) // my custom validator
id: number;
}
@Get(':companyId/departments/:departmentId/employees')
getEmployees(
@Param('companyId') companyId: ResourceId,
@Param('departmentId') departmentId: ResourceId,
) {}
У меня есть несколько случаев, когда в одном маршруте более одного параметра. Я не хотел бы создавать отдельный класс проверки для каждого маршрута. Есть ли способ решить эту проблему по-другому?
2 ответа
По состоянию на 2022 год в документах NestJS говорится, что можно проверить параметры маршрута с помощью встроенного канала проверки.
В контроллере:
@Get(':id')
findOne(@Param() params: FindOneParams) {
return 'This action returns a user';
}
Класс проверки:
import { IsNumberString } from 'class-validator';
export class FindOneParams {
@IsNumberString()
id: number;
}
Ссылка: https://docs.nestjs.com/techniques/validation#auto-validation
Проблема в том, что у вас есть простая строка здесь. Для проверки с class-validator
чтобы работать, вы должны создать экземпляр класса, в вашем случае ResourceId
, Встроенный ValidationPipe
ожидает, что значение будет {id: '123'}
вместо '123'
чтобы иметь возможность преобразовать его автоматически. Но вы можете легко создать свой собственный канал проверки, который выполняет это дополнительное преобразование.
export class ParamValidationPipe implements PipeTransform {
async transform(value, metadata: ArgumentMetadata) {
if (metadata.type === 'param') {
// This is the relevant part: value -> { id: value }
const valueInstance = plainToClass(metadata.metatype, { id: value });
const validationErrors = await validate(valueInstance);
if (validationErrors.length > 0) {
throw new BadRequestException(validationErrors, 'Invalid route param');
}
return valueInstance;
} else {
return value;
}
}
}
Затем вы можете использовать его на своем контроллере:
@UsePipes(ParamValidationPipe)
@Get(':companyId/departments/:departmentId/employees')
getEmployees(
@Param('companyId') companyId: ResourceId,
@Param('departmentId') departmentId: ResourceId,
) {
return `id1: ${companyId.id}, id2: ${departmentId.id}`;
}