GraphQL-транспортность c. Хотя службы GraphQL обычно являются веб-службами, которые принимают запросы по HTTP, они могут принимать запросы и по другим транспортным средствам. На самом деле служба GraphQL может выполнять запросы вообще без сетевых запросов - все, что ей нужно - это запрос, и, необязательно, объект переменных и имя операции.
Из-за этого GraphQL spe c не касается методов, кодов состояния или чего-либо еще, указывающего c на HTTP (он упоминает только HTTP при обсуждении сериализации). Любые практики в отношении этих вещей в лучшем случае являются соглашениями, которые либо развивались с течением времени, либо были просто артефактами некоторых оригинальных библиотек, написанных для GraphQL. Таким образом, любой ответ на ваш вопрос будет главным образом основываться на мнении.
При этом , поскольку вашей службе GraphQL не должно быть важно, как ее запросы принимаются, возможно должно быть разделение между его кодом и любым кодом, обрабатывающим получение запросов и отправку ответов назад (как приложение Express в Node.js). Другими словами, мы могли бы сказать, что никогда нормально, если код вашего преобразователя изменяет такие вещи, как код состояния ответа. Это текущее мнение сообщества, и большинство библиотек возвращают только один из двух кодов - 400, если сам запрос как-то недействителен, и 200 в противном случае.
Если вся ваша конечная точка GraphQL защищена некоторыми логинами аутентификации c (скажем, ваш сервер проверяет наличие какого-либо значения заголовка), тогда запрос GraphQL может вернуться со статусом 401. Но это то, что мы обрабатываем на уровне веб-сервера, а не как часть вашей схемы. Ничего не изменилось, если что-то пошло не так с кодом вашего веб-сервера, и он должен был вернуть статус 500, или сервер nginx перед вами возвратил 494 (слишком большой заголовок запроса), et c.
Традиционно, ошибки, возникающие при выполнении, должны быть выброшены, и все Расширения GraphQL могут использоваться для предоставления дополнительного контекста, когда ошибки собираются и сериализуются - имя ошибки, трассировка стека и т. Д. c. Однако не имеет смысла включать коды ошибок HTTP в эти ошибки, когда, опять же, ошибки не имеют ничего общего с HTTP. Это излишне смешивает несвязанные понятия - если вы хотите определить тип ошибки, вам лучше использовать описательные коды, такие как GENERIC_SERVER
, INVALID_INPUT
и т. Д. c.
Однако существуют соглашения, касающиеся обработка ошибок также меняется. Некоторые службы хотят лучше отличать guish ошибок клиента от других ошибок выполнения. Становится все более привычным видеть ошибки проверки или другие ошибки, которые будут показаны конечному пользователю и возвращены как часть data
вместо того, чтобы рассматриваться как ошибка выполнения.
type Mutation {
login(username: String!, password: String!): LoginPayload!
}
type LoginPayload {
user: User
error: Error
}
Вы можете видеть типы полезной нагрузки, подобные этим, в действии с API-интерфейсами publi c, такими как Shopify. Вариант этого подхода состоит в том, чтобы использовать объединения для представления ряда возможных ответов.
type Mutation {
login(username: String!, password: String!): LoginPayload!
}
union LoginPayload = User | InvalidCredentialsError | ExceededLoginAttemptsError
Конечный результат состоит в том, что клиентские ошибки строго типизированы и их легко отличить от других ошибок, которые конечный пользователь не делает заботиться. Принятие такого рода соглашений дает много преимуществ, но в конечном итоге решать, подходят ли они для вашего сервера.