代码之家  ›  专栏  ›  技术社区  ›  Ryuzaki L

如何自定义GraphQL查询验证错误消息

  •  0
  • Ryuzaki L  · 技术社区  · 5 年前

    我正在使用在数据库上实现查询层 GraphQl 以及spring boot项目,对sql数据库执行CRUD操作。在GraphQL模式中,我提到了一些必填字段,当查询中没有提到这些字段时,它将返回 ValidationError 默认格式的错误消息 200 状态代码。

    错误:

    {
    "data": null,
    "errors": [
        {
             value=StringValue{value='1235'}}]}}]}' is missing required fields '[book_type]' @ 'create_book'",
            "locations": [
                {
                    "line": 3,
                    "column": 23,
                    "sourceName": null
                }
            ],
            "description": "argument 'insert' with value value=StringValue{value='1235'}}]}}]}' is missing required fields '[book_type]'",
            "validationErrorType": "WrongType",
            "queryPath": [
                "create_book"
            ],
            "errorType": "ValidationError",
            "path": null,
            "extensions": null
        }
    ],
    "dataPresent": false,
    "extensions": null
    }
    

    这是我的层架构模式代码

    控制器:

    @Autowired
    private GraphQLServer graphQlServer;
    
    @PostMapping("test")
    public ResponseEntity<Object> graphQl(@RequestBody String body){
        ExecutionResult response = graphQlServer.execute(body);
    
        return ResponseEntity.ok(response);
    }
    

    服务:

    @Service
    public class GraphQLServer {
    
    @Autowired
    private GraphQL graphQl;
    
    public ExecutionResult execute(String query) {
        return graphQl.execute(query);
       }
    
    }
    

    配置:

    @Bean
    public GraphQL loadSchema() throws IOException {
    
        File schemaFile = schemaResource.getFile();
    
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(schemaFile);
        RuntimeWiring wiring = buildRuntimeWiring();
        GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(typeRegistry, wiring);
        return GraphQL.newGraphQL(schema).build();
    }
    
    private RuntimeWiring buildRuntimeWiring() {
    
        return RuntimeWiring.newRuntimeWiring()
                .type("Mutation", mutationWiring -> mutationWiring.dataFetcher("create_book", bookDataFetcher))
                .build();
    
    }
    

    BookDataFetcher:

    @Override
    public Map<String, Object> get(DataFetchingEnvironment environment) {
    
        //return data from db by getting Map properties from environment
    
    }
    

    上面的代码按预期工作,但我的问题是 如何自定义错误消息? 在错误消息中,我想提及状态 400 因为这是来自客户端的错误请求

    0 回复  |  直到 5 年前
        1
  •  1
  •   Ken Chan    5 年前

    首先,你应该打电话 toSpecification() ExecutionResult 以确保响应符合 GraphQL Specification .

    默认情况下,只有一个 执行结果 的实现由提供 这是 ExecutionResultImpl ,这样你就可以投 执行结果 为了使用它 transform() 以更新其状态。

    执行结果示例 内部包含由检测到的所有错误 。它们都属于 GraphQLError 这意味着您必须在定制过程中将其转换为特定的子类。

    在你的例子中,子类是 ValidationError 代码看起来像:

    @PostMapping("test")
    public ResponseEntity<Object> graphQl(@RequestBody String body){
    
        ExecutionResult response = graphQlServer.execute(body);
    
        ExecutionResultImpl responseImpl = (ExecutionResultImpl) response;
    
        List<GraphQLError> customizedErrors = Lists.newArrayList();
        for (GraphQLError gqlError : responseImpl.getErrors()) {
                //Do your error custmosation here....
                GraphQLError customizedError = gqlError;
                if (gqlError instanceof ValidationError) {
                    ValidationError error = (ValidationError) gqlError;
                    customizedError = new ValidationError(error.getValidationErrorType(), error.getLocations(),
                            "Customizing some error message blablabla....");
                }
                customizedErrors.add(customizedError);
        }
    
        Map<String, Object> specResponse = responseImpl.transform(b->b.errors(customizedErrors)).toSpecification();
    
        return ResponseEntity.ok(specResponse);
    }