在GraphQL中,通过在响应中添加一个错误块来支持错误报告是很常见的。响应可以同时包含数据和错误,例如,当一些字段被成功解决,但其他字段有错误。有错误的字段被设置为空,并且错误被添加到错误块中。
DGS框架有一个开箱即用的异常处理程序,该程序按照本页面错误规范部分所描述的规范工作。这个异常处理程序处理来自数据提取器的异常。任何 RuntimeException 都会被翻译成 INTERNAL 类型的 GraphQLError。对于一些特定的异常类型,会使用一个更具体的GraphQL错误类型。
当@安全检查失败的时候。当请求的实体(例如基于查询参数)没有被找到时,开发者会抛出这个问题。
将应用程序特定的异常映射到有意义的异常回客户端是很有用的。您可以通过注册 DataFetcherExceptionHandler 来做到这一点。确保委托给 DefaultDataFetcherExceptionHandler 类,这是框架的默认异常处理程序。如果你不委托给这个类,你就会失去框架的内置异常处理程序。
以下是自定义异常处理程序实现的示例。
@Component
public class CustomDataFetchingExceptionHandler implements DataFetcherExceptionHandler {
@Override
public CompletableFuture<DataFetcherExceptionHandlerResult> handleException(DataFetcherExceptionHandlerParameters handlerParameters) {
if (handlerParameters.getException() instanceof MyException) {
Map<String, Object> debugInfo = new HashMap<>();
debugInfo.put("somefield", "somevalue");
GraphQLError graphqlError = TypedGraphQLError.newInternalErrorBuilder()
.message("This custom thing went wrong!")
.debugInfo(debugInfo)
.path(handlerParameters.getPath()).build();
DataFetcherExceptionHandlerResult result = DataFetcherExceptionHandlerResult.newResult()
.error(graphqlError)
.build();
return CompletableFuture.completedFuture(result);
} else {
return DataFetcherExceptionHandler.super.handleException(handlerParameters);
}
}
}
以下数据提取器抛出 MyException
@DgsComponent
public class HelloDataFetcher {
@DgsData(parentType = "Query", field = "hello")
@DgsEnableDataFetcherInstrumentation(false)
public String hello(DataFetchingEnvironment dfe) {
throw new MyException();
}
}
查询 hello 字段会产生以下响应。
{
"errors": [
{
"message": "This custom thing went wrong!",
"locations": [],
"path": [
"hello"
],
"extensions": {
"errorType": "INTERNAL",
"debugInfo": {
"somefield": "somevalue"
}
}
}
],
"data": {
"hello": null
}
}
对于 GraphQL,我们通常会遇到两类错误:
1、综合错误。这些是意外错误,并不代表最终用户可以修复的情况。这种错误通常适用于许多类型和领域。此类错误出现在 GraphQL 响应的错误数组中。
2、作为数据的错误。这些是对终端用户有参考价值的错误(例如。"这个标题在你的国家不可用 "或 “你的帐户已被暂停”)。这类错误通常是特定的用例,只适用于某些字段或某些字段的子集。这些错误是GraphQL模式的一部分。
GraphQL 规范对错误的结构提供了最低限度的指导。唯一需要的字段是消息字符串,它没有定义的格式。在 Studio Edge 中,我们希望拥有更强大、更具表现力的合约。这是我们使用的定义
一个代码位置数组,其中每个位置都是一个带有键 line 和 column 的映射,两个自然数都从 1 开始,描述相关语法元素的开头
如果错误与响应中的一个或多个特定字段相关联,则此错误字段会详细说明遇到错误的那些响应字段的路径(这允许客户端识别空结果是故意的还是由运行时错误引起的
"""
Error format as defined in GraphQL Spec
"""
interface GraphQLError {
message: String! // Required by GraphQL Spec
locations: [Location] // See GraphQL Spec
path: [String | Int] // See GraphQL Spec
extensions: TypedError
}
Studio Edge 将 TypedError 定义如下:
枚举式的错误代码,意在对错误进行相当粗略的描述,足以满足客户端的分支逻辑。
枚举,提供关于错误的更多细节,包括它的具体原因(这个枚举的元素可能会改变,这里没有记录)。
发布错误的来源名称(例如,后台服务、DGS、网关、客户端库或客户端应用程序的名称)。
如果该请求包括一个标志,表明它需要调试信息,这个字段包含了额外的信息(如堆栈跟踪或来自上游服务的额外报告)。
包含可能有助于调试错误的额外信息的页面的URI(这可能是此类错误的通用页面,也可能是关于特定错误实例的特定页面)。
下表显示了可用的 ErrorType 枚举值: