控制器的嵌套路由中的 Nestjs 验证失败(需要数字字符串)

J.D*_*J.D 1 nestjs

我有一个使用@Controller('tasks')装饰器的控制器。在这个控制器中,我有一个路由@Get('/week'),通常请求应该去localhost:4000/tasks/week但它返回一个错误的请求:

{
    "statusCode": 400,
    "error": "Bad Request",
    "message": "Validation failed (numeric string is expected)"
}
Run Code Online (Sandbox Code Playgroud)

下面是我的代码:

@Controller('tasks')
@UseGuards(AuthGuard())
export class TasksController {
  constructor(private tasksService: TasksService) { }

  @Get('/:id')
  getTaskById(@Param('id', ParseIntPipe) id: number): Promise<Task> {
    return this.tasksService.getTaskById(id);
  }

  @Get('/week')
  getTasksByWeek(@GetUser() user: User): Promise<Task[]> {
    return this.tasksService.getTasksByWeek(user);
}
Run Code Online (Sandbox Code Playgroud)

从 Get() 装饰器中删除/week有效但不添加它。

预期结果:返回数据

实际结果

 {
    "statusCode": 400,
    "error": "Bad Request",
    "message": "Validation failed (numeric string is expected)"
}
Run Code Online (Sandbox Code Playgroud)

mil*_*ion 17

由于给出的答案并没有真正解释这种行为的“原因”,这里有一个快速解释:

这只是一个顺序和满足什么路线的问题。 首先:“week”被误认为是“:id”,例如 123、204...等。

当您的路由器尝试满足路由要求(本例中为模式)的第一条路由时,您的请求将转发到 /id 路由。它发生在每个带有路由器的 http 框架中。

验证稍后进行。简而言之,在路由选择中唯一重要的是模式,而不是其中的验证集。

这个顺序非常重要,因为您将在所有带有路由器的主要 http 框架中面临同样的问题。


J.D*_*J.D 7

我找到了解决此问题的方法。诸如 Get('week') 之类的路由或接受参数的路由应排在具有基本控制器路由的路由之前。

假设我们有一个像下面这样的路由 @GET() 来获取所有任务:

 @Get()
  getTasks(@GetUser() user: User): Promise<Task[]> {
    return this.tasksService.getTasksByWeek(user);
}
Run Code Online (Sandbox Code Playgroud)

它应该如何在代码中:

@Controller('tasks')
@UseGuards(AuthGuard())
export class TasksController {
  constructor(private tasksService: TasksService) { }

  @Get('/:id')
  getTaskById(@Param('id', ParseIntPipe) id: number): Promise<Task> {
    return this.tasksService.getTaskById(id);
  }

  @Get('/week')
  getTasksByWeek(@GetUser() user: User): Promise<Task[]> {
    return this.tasksService.getTasksByWeek(user);
}
 @Get()
  getTasks(@GetUser() user: User): Promise<Task[]> {
    return this.tasksService.getTasksByWeek(user);
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个奇怪的解决方案 (2认同)

Mat*_*ski 5

只需将@Get("any-string")路由放在接受参数的路由@Get(":id")之上即可。