23t*_*tux 13 http-status-codes graphql
很多资源都说,GraphQL 应该始终以 200 状态代码响应,即使发生错误:
因为 GraphQL 可以在一个响应中返回多个响应,所以这是有道理的。当用户在一个请求中请求两个资源,并且只能访问第一个资源时,您可以发回第一个资源并forbidden
为第二个资源返回错误。
然而,这只是我在阅读多个 GraphQL 库和博客文章的文档的过程中想到的。我在官方规范中没有找到任何关于 HTTP 状态代码的信息,这里是https://spec.graphql.org/或这里是https://graphql.org/
errors
{
"errors" => [{
"message" => "Graphql::Forbidden",
"locations" => [],
"extensions" => {
"error_class" => "Graphql::Forbidden", "status" => 403
}
}]
}
Run Code Online (Sandbox Code Playgroud)
400 Bad Request
吗?{
"errors" => [{
"message" => "Field 'foobar' doesn't exist on type 'UserConnection'",
"locations" => [{
"line" => 1,
"column" => 11
}],
"path" => ["query", "users", "foobar"],
"extensions" => {
"status" => 400, "code" => "undefinedField", "typeName" => "UserConnection", "fieldName" => "foobar"
}
}]
}
Run Code Online (Sandbox Code Playgroud)
如果您能在 GraphQL 中处理 HTTP 状态代码时分享您的经验/资源/最佳实践,我会很棒。
Dan*_*den 21
GraphQL 与传输无关。虽然 GraphQL 服务通常是通过 HTTP 接受请求的 Web 服务,但它们也可以并且确实接受通过其他传输的请求。事实上,GraphQL 服务可以在完全没有网络请求的情况下执行查询——它所需要的只是一个查询,以及可选的变量对象和操作名称。
正因为如此,GraphQL 规范不关心方法、状态代码或任何其他特定于 HTTP 的东西(它只在讨论序列化时提到 HTTP)。关于这些事情的任何实践充其量只是随着时间的推移而演变的约定,或者只是一些为 GraphQL 编写的原始库的产物。因此,对您的问题的任何回答都将主要基于意见。
也就是说,因为你的 GraphQL 服务不应该关心它的查询是如何接收的,可以说它的代码和处理接收请求和发回响应的任何代码之间应该有一个分离(就像 Node.js 中的 Express 应用程序) . 换句话说,我们可以说你的解析器代码永远不会改变响应的状态代码之类的东西。这是社区当前的想法,大多数库只返回两个代码之一——如果请求本身无效,则为 400,否则为 200。
如果您的整个 GraphQL 端点由某些身份验证逻辑保护(假设您的服务器检查某些标头值),那么 GraphQL 请求可能会返回 401 状态。但这是我们在 Web 服务器级别处理的事情,而不是您架构的一部分。如果您的 Web 服务器代码出现严重错误并且必须返回 500 状态,或者位于您前面的 nginx 服务器返回 494(请求标头太大)等,这并没有什么不同。
传统上,执行过程中遇到的错误应该被抛出,仅此而已。GraphQL 扩展可用于在错误被收集和序列化时提供额外的上下文——错误的名称、堆栈跟踪等。 然而,当再次出现错误时,将HTTP状态代码包含在这些错误中是没有意义的与 HTTP 无关。这样做不必要的混合无关的概念-如果你想找出错误的类型,你最好使用描述性的代码一样GENERIC_SERVER
,INVALID_INPUT
等等。
但是,有关错误处理的约定也在发生变化。一些服务希望更好地将客户端错误与其他执行错误区分开来。越来越常见的情况是,验证错误或其他错误会显示给最终用户,并作为data
执行错误的一部分返回,而不是被视为执行错误。
type Mutation {
login(username: String!, password: String!): LoginPayload!
}
type LoginPayload {
user: User
error: Error
}
Run Code Online (Sandbox Code Playgroud)
您可以使用 Shopify 等公共 API 来查看此类有效负载类型。这种方法的一个变体是利用联合来表示许多可能的响应。
type Mutation {
login(username: String!, password: String!): LoginPayload!
}
union LoginPayload = User | InvalidCredentialsError | ExceededLoginAttemptsError
Run Code Online (Sandbox Code Playgroud)
最终结果是客户端错误是强类型的,并且很容易与最终用户不关心的其他错误区分开来。采用这些约定有很多好处,但它们是否适合您的服务器最终取决于您。
归档时间: |
|
查看次数: |
5925 次 |
最近记录: |