graphql- java данные об ошибках (например, расширения) вставляются в поле «сообщения» на клиенте - PullRequest
1 голос
/ 07 марта 2020

В graphql- java я переопределяю getExtensions в GraphQLError, чтобы передать расширение «code» для использования клиентом Apollo.

Когда я добавил точку останова, я вижу, что GraphQLObjectMapper видит ошибку в executeResult со всеми его полями, включая расширения, правильно установленные как и ожидалось.

Однако, когда ошибка достигает значения apollo, она странным образом преобразуется и появляется весь объект ошибки (включая массив расширений) быть вставленным в поле строкового сообщения следующим образом:

    {
  "errors": [
    {
      "message": "Unexpected error value: { message: \"Exception while fetching data (/myQuery) : Didn't work\", locations: [[Object]], path: [\"myQuery\"], extensions: { code: \"MY_CODE\", classification: \"DataFetchingException\" } }",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "mailLabels"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR"
      }
    }
  ],
  "data": null
}

Насколько я могу судить, apollo не делает ничего плохого. Я подозреваю, что graphql- java может быть тем, кто вставляет всю эту ошибку в поле "message" и затем устанавливает код как "INTERNAL_SERVER_ERROR", но я не совсем уверен. Могу ли я что-то сделать на graphql- java конец, чтобы предотвратить это и заставить его правильно передавать расширения и не вставлять их в значение сообщения? Любая помощь будет оценена.

1 Ответ

0 голосов
/ 07 марта 2020

Это вызвано не graphql-java, а graphql-java-servlet. В некоторых старых версиях по умолчанию он не сериализует GraphQLError в структуру, определенную спецификацией GraphQL, которая должна быть исправлена ​​в 7.5.1 в этом выпуске .

Если вы не можете обновить до последней версии, самый простой способ - настроить GraphQLObjectMapper и переопределить его convertSanitizedExecutionResult:

public class CustomObjectMapper extends GraphQLObjectMapper {

    @Override
    public Map<String, Object> convertSanitizedExecutionResult(ExecutionResult executionResult, boolean includeData) {
        Map<String, Object>  result = super.convertSanitizedExecutionResult(executionResult, includeData);
        if(result.containsKey("errors")){
            result.put("errors", executionResult.getErrors().stream().map(err->err.toSpecification()).collect(toList()));
        }
    }
}
...