JWo*_*JWo 0 rest typescript nestjs
我的 REST API 中有一个查询参数,其值应受枚举类型的限制。当客户端给出不同的东西时,我正在寻找一种抛出“错误请求”错误的方法。
我的枚举看起来像这样:
export enum Precision {
S = 's',
MS = 'ms',
U = 'u',
NS = 'ns',
}
Run Code Online (Sandbox Code Playgroud)
我的控制器功能如下所示:
@Get(':deviceId/:datapoint/last')
@ApiOkResponse()
@ApiQuery({name: 'precision', enum: Precision})
getLastMeasurement(
@Param('deviceId') deviceId: string,
@Param('datapoint') datapoint: string,
@Query('precision') precision: Precision = Precision.S,
@Res() response: Response,
) {
console.log(precision);
....
response.status(HttpStatus.OK).send(body);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是该函数也接受其他值(例如,我可以发送 f 作为查询参数的值)。该函数不会向客户端返回错误,但我不想在每个控制器函数的开头编写 if else 块。
我想对此有一个相当简单的解决方案,但是当我尝试在互联网上查找它时,我总是在 DTO 中获得类验证的结果,而不是直接在查询参数/REST 控制器中进行简单的枚举验证。
谢谢你的时间,
J
这里有2个问题。
第一个是您precision以错误的方式传递params的默认值。你必须DefaultValuePipe像这样使用:
getLastMeasurement(
... // some other params
@Query('precision', new DefaultValuePipe(Precision.S)) precision: Precision
) {
... // do something
}
Run Code Online (Sandbox Code Playgroud)
第二个是枚举验证。NestJS 只提供了 6 种验证管道,它们都没有验证枚举,因此您必须创建自己的自定义验证管道来验证枚举。
有两种可能的方法可以做到这一点:
基于这个https://docs.nestjs.com/pipes#custom-pipes,它会是这样的:
import { BadRequestException, PipeTransform } from '@nestjs/common';
import { isDefined, isEnum } from 'class-validator';
export class PrecisionValidationPipe implements PipeTransform<string, Promise<Precision>> {
transform(value: string): Promise<Precision> {
if (isDefined(value) && isEnum(value, Precision)) {
return Precision[value];
} else {
const errorMessage = `the value ${value} is not valid. See the acceptable values: ${Object.keys(
Precision
).map(key => Precision[key])}`;
throw new BadRequestException(errorMessage);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的请求中,就像
getLastMeasurement(
@Query('precision', PrecisionValidationPipe, new DefaultValuePipe(Precision.S)) precision: Precision,
) {
console.log(precision);
....
response.status(HttpStatus.OK).send(body);
}
Run Code Online (Sandbox Code Playgroud)
import { BadRequestException, Injectable, PipeTransform } from '@nestjs/common';
import { isDefined, isEnum } from 'class-validator';
@Injectable()
export class EnumValidationPipe implements PipeTransform<string, Promise<any>> {
constructor(private enumEntity: any) {}
transform(value: string): Promise<any> {
if (isDefined(value) && isEnum(value, this.enumEntity)) {
return this.enumEntity[value];
} else {
const errorMessage = `the value ${value} is not valid. See the acceptable values: ${Object.keys(this.enumEntity).map(key => this.enumEntity[key])}`;
throw new BadRequestException(errorMessage);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的请求中,就像
getLastMeasurement(
@Query('precision', new EnumValidationPipe(Precision), new DefaultValuePipe(Precision.S)) precision: Precision,
) {
console.log(precision);
....
response.status(HttpStatus.OK).send(body);
}
Run Code Online (Sandbox Code Playgroud)
您应该能够创建一个像LastMeasurementQueryParams这样使用类验证器装饰器的类,并使用内置的 ValidationPipe来检查并确保发送了预期值之一。
该类可能看起来像这样:
export class LastMeasurementQueryParams {
@IsEnum(Precision)
precision: Precision;
}
Run Code Online (Sandbox Code Playgroud)
然后你的控制器看起来像这样:
@Get(':deviceId/:datapoint/last')
@ApiOkResponse()
@ApiQuery({name: 'precision', enum: Precision})
getLastMeasurement(
@Param('deviceId') deviceId: string,
@Param('datapoint') datapoint: string,
@Query('precision') precision: LastMeasurementQueryParams = { precision: Precision.S },
@Res() response: Response,
) {
console.log(precision);
....
response.status(HttpStatus.OK).send(body);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1620 次 |
| 最近记录: |