为什么 NestJS GraphQL 验证错误没有放置在错误消息字段中?

Cal*_*gal 5 nestjs

我在意外的位置看到了一些类验证器错误。我希望有一种更方便的格式来处理错误,但也许我不知道一些用于处理扩展字段中对象的 graphQL 技巧......

在运行 NestJS sample/23-graphql-code-first 时,我在 GraphQL 游乐场中看到以下内容:

有输入:

  addRecipe(newRecipeData: {
    description: "too short"
    title: "this field should fail for being too long"
    ingredients: ["normal"]

  }) {
    title
  }
}
Run Code Online (Sandbox Code Playgroud)

我回来了:

  "errors": [
    {
      "message": "Bad Request Exception",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "addRecipe"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "response": {
            "statusCode": 400,
            "message": [
              "title must be shorter than or equal to 30 characters",
              "description must be longer than or equal to 30 characters"
            ],
            "error": "Bad Request"
          },
          "status": 400,
          "message": "Bad Request Exception",
          "stacktrace": [
            "Error: Bad Request Exception",
            "    at ValidationPipe.exceptionFactory nest/sample/23-graphql-code-first/node_modules/@nestjs/common/pipes/validation.pipe.js:78:20)",
          ...
          ]
        }
      }
    }
  ],
  "data": null
}
Run Code Online (Sandbox Code Playgroud)

这些错误是深层嵌套的,“错误请求异常”没有那么有用。这是否按预期工作?

Leo*_*mes 12

最佳解决方案基于此官方评论:创建您自己的formatErrorformatResponse函数。

我刚刚在 GitHub 上的这个项目中使用它,它运行良好!

我的样品:

    import { GraphQLError, GraphQLFormattedError } from 'graphql';
    
    GraphQLModule.forRoot({
      autoSchemaFile: true,
      debug: false,
      formatError: (error: GraphQLError) => {
        const graphQLFormattedError: GraphQLFormattedError = {
          message: error.extensions.exception.response.message || error.message,
        };
        return graphQLFormattedError;
      },
    }),
Run Code Online (Sandbox Code Playgroud)

现在,我收到来自 GraphQL 的格式化错误响应:

{
  "errors": [
    {
      "message": [
        "firstName must be longer than or equal to 1 characters",
        "lastName must be longer than or equal to 1 characters"
      ]
    }
  ],
  "data": null
}
Run Code Online (Sandbox Code Playgroud)

  • 这给了我一个 TS 错误:“类型 '{ code?: string | undefined; stacktrace?: readonly string[] | undefined; }' 上不存在属性 'response'。” (4认同)

小智 5

如果你正在使用mercurius,你可以使用这个:

// In main.ts file, just register ValidationPipe like normal
app.useGlobalPipes(new ValidationPipe({ forbidUnknownValues: true }))
Run Code Online (Sandbox Code Playgroud)
// In app.module.ts file, add this errorFormatter:
GraphQLModule.forRoot<MercuriusDriverConfig>({
  ...
  errorFormatter: execution => {
    const [error] = execution.errors // take first error
    const originalError = error?.originalError
    if (originalError instanceof HttpException)
      return {
        statusCode: originalError.getStatus(),
        response: { data: originalError.getResponse() as any }
      }
    return { statusCode: 500, response: execution }
  }
})
Run Code Online (Sandbox Code Playgroud)


小智 1

当您使用验证管道时,您可以更改该行为:

app.useGlobalPipes(
    new ValidationPipe({
      exceptionFactory: errors => new BadRequestException(errors), // TODO: Use graphql errors instead
      forbidUnknownValues: true,
    }),
  );
Run Code Online (Sandbox Code Playgroud)