0

我正在使用 GraphQL-SPQR 和 Spring Boot 运行 GraphQL API。

目前,我正在抛出RuntimeExceptions 以返回 GraphQL 错误。我有一个以正确格式返回错误的customExceptionHandler实现DataFetcherExceptionHandler,如下所示:

class CustomExceptionHandler : DataFetcherExceptionHandler {
    override fun onException(handlerParameters: DataFetcherExceptionHandlerParameters?): DataFetcherExceptionHandlerResult {


        // get exception
        var exception = handlerParameters?.exception
        val locations = listOf(handlerParameters?.sourceLocation)
        val path = listOf(handlerParameters?.path?.segmentName)

        // create a GraphQLError from your exception
        if (exception !is GraphQLError) {
            exception = CustomGraphQLError(exception?.localizedMessage, locations, path)
        }

        // cast to GraphQLError
        exception as CustomGraphQLError

        exception.locations = locations
        exception.path = path

        val errors = listOf<GraphQLError>(exception)

        return DataFetcherExceptionHandlerResult.Builder().errors(errors).build()
    }
}

我使用CustomExceptionHandler如下(在我的主应用程序类中):

@Bean
    fun graphQL(schema: GraphQLSchema): GraphQL {
        return GraphQL.newGraphQL(schema)
                .queryExecutionStrategy(AsyncExecutionStrategy(CustomExceptionHandler()))
                .mutationExecutionStrategy(AsyncSerialExecutionStrategy(CustomExceptionHandler()))
                .build()
    }

我想为与异常对应的 UUID 设置一个标头变量,用于记录目的。我该怎么做?

更好的是,是否可以创建一个 Spring Bean 将 UUID 放在所有查询和突变的标头中?

谢谢!

4

1 回答 1

1

当您使用弹簧靴时,有两种选择:

  • 您正在使用 spring boot graphql spqr starter(它带有自己的控制器来处理所有 graphQL 请求)
  • 您正在使用普通的 graphql-spqr 并拥有自己的控制器来处理 GraphQL 请求

无论如何,您有几个选择:

使您的 CustomExceptionHandler 成为 Spring Bean 并自动装配 HttpServletResponse

这可能是最简单的方法 - 它可能在任何情况下都可以工作:您可以简单地将您的 CustomExceptionHandler 设为 Spring bean 并让它自动装配 HttpServletRequest - 在处理程序方法中,您可以将其设置为您想要的任何内容它是。这是Java中的一些虚拟代码(对不起,我对Kotlin不够精通):

@Component
class CustomExceptionHandler implements DataFetcherExceptionHandler {
    private final HttpServletResponse response; 

    public CustomExceptionHandler(HttpServletResponse response) {
        this.response = response; 
    }

    @Override
    public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandlerParameters handlerParameters) {
        response.setHeader("X-Request-ID", UUID.randomUUID().toString());
        // ... your actual error handling code
    }
}

这将起作用,因为 spring 将意识到每个请求的 HttpServletRequest 都不同。因此,它将向您的错误处理程序注入一个动态代理,该代理将指向每个请求的实际 HttpServletResponse 实例。

我会争辩说,这不是最优雅的方式,但它肯定会解决你的问题。

对于 graphql-spqr 弹簧启动器

在使用此启动器的项目中使用了一个默认控制器实现。该控制器将处理您收到的每个 graphql 请求。您可以通过实现自己的GraphQLExecutor并使其成为 spring bean 来自定义它。该执行器负责调用 GraphQL 引擎,将参数传入并输出响应。这是默认实现,您可能希望以此为基础。

与之前的解决方案类似,您可以在该类中自动装配 HttpServletResponse 并设置 HTTP 响应标头。

该解决方案将允许您决定是否要在所有情况下设置请求 ID,或者仅在特定错误情况下设置。(graphql.execute返回一个对象,如果存在错误以及存在哪些错误,您可以从中获取信息)

在没有 spring boot starter 的情况下使用 graphql-spqr

找到您的 GraphQL 控制器,为 HttpServletRequest 类型的该方法添加一个参数 - 然后根据您的喜好添加标头(请参阅上一节关于一些更具体的建议)

于 2019-11-28T08:57:11.073 回答