Apollo-link-rest: Рекомендуемая стратегия для обработки ошибок 404?

Созданный на 6 июн. 2018  ·  12Комментарии  ·  Источник: apollographql/apollo-link-rest


REST API довольно часто использует ответ 404, чтобы указать, что запись не существует. Прямо сейчас, когда это происходит, результатом является networkError который по умолчанию рассматривается стеком Apollo как более фатальная ошибка, чем ошибка GraphQL.

Например, с запросом:

query BookQuery($slug: ID!) {
  book(slug: $slug) @rest(type: "Book", path: "book/:slug") {
    name
    author
  }
}

Если конечная точка возвращает 404, она отклоняется с сетевой ошибкой, которая должна быть обработана там, где намерение, вероятно, просто использует опору error render для отображения сообщения о нефатальной ошибке для пользователя. т.е. если бы это был запрос GraphQL, а не REST, это не было бы классифицировано как сетевая ошибка, и это было бы обработано таким образом.

Чтобы исправить это, я добавил в свой собственный error-link проверку, которая преобразует ошибку сети 404 в ошибку GraphQL:

forward(operation).subscribe({
  next: result => {...},
  error: networkError => {
    if (networkError.statusCode === 404) {
      return observer.next({errors: [networkError]});
    }
    //...
    observer.error(networkError);
  },
  complete: observer.complete.bind(observer),
});

В этом, вероятно, еще есть возможности для улучшения, но это решает проблему.

Мне было интересно, можно ли / нужно ли как-то решить эту проблему в apollo-link-rest , поэтому я решил, что начну разговор.

enhancement💡 question❔

Все 12 Комментарий

Отличный вопрос. - Я бы хотел, чтобы этот шаблон был добавлен в качестве предложения в документацию. Я думаю, что это класс проблем, от которых страдают множественные apollo-ссылки (на ум приходит apollo-link-state).

Однако я не знаю, уверены ли мы, что это правильный ответ для всех пользователей ApolloLink?

В настоящее время так обрабатываются все HTTP-ошибки в apollo-link-rest.

        if (res.status >= 300) {
          // Throw a JSError, that will be available under the
          // "Network error" category in apollo-link-error
          let parsed: any;
          try {
            parsed = await res.json();
          } catch (error) {
            // its not json
            parsed = await res.text();
          }
          rethrowServerSideError(
            res,
            parsed,
            `Response not successful: Received status code ${res.status}`,
          );
        }
        return res;

возможно, мы добавим функцию сопоставления регистра, которая позволяет пользователям определять, как обрабатывать ошибку?
Может предоставить полезные утилиты по умолчанию для общих случаев, например 404 == null

Хотя я разделяю озабоченность @fbartho тем, что предлагаемое нами решение может не подходить для всех пользователей этой ссылки, я подумал об одном случае, когда ошибка 404 особенно опасна. Если взять этот пример из тестов:

query postAndTags {
  post @rest(type: "Post", path: "/post/1") {
    id
    title
  }
  tags @rest(type: "[Tag]", path: "/tags") {
    name
  }
}

и post не существует и возвращает 404, тогда весь запрос не выполняется из-за сетевой ошибки. Хотя в некоторых случаях это может быть желательным, кажется, что результат должен быть таким:

const data = {
  post: null,
  tags: [{ name: 'apollo' }, { name: 'graphql' }],
}

Если мы хотим удовлетворить это, добавить дополнительную обработку ошибок, как предлагает @paulpdaniels, будет довольно легко. Просматривая ошибки 4xx, я действительно вижу только 404 и 400/412/422 (при мутациях), которые, возможно, являются нефатальными ошибками, требующими специального лечения, либо как ошибки GraphQL, либо устанавливая результат равным null .

Остается вопрос, разумно ли предоставить какой-либо фиксированный обработчик для этих ошибок или оставить его на error-link или приложения. Поскольку множественные запросы на мутацию не поддерживаются (я думаю?), Единственный текущий недостаток, который кажется особенно актуальным, - это пример 404, с которого я начал выше.

Также есть возможность добавить обработчик ошибок в конфигурацию, но похоже, что это может украсть функциональность у error-link который действительно принадлежит ему. Это также может сделать API этой ссылки излишне сложным.

@marnusw Отличный ответ. Я бы поддержал исправление, реализующее ваше поведение по умолчанию!

142 добавляет обработку ошибок 404. Я думаю, что это самое главное в этой дискуссии.

Основываясь на многих стандартах rest api , все коды ошибок всегда должны содержать удобочитаемое сообщение. Обнуление этого результата, как это было сделано в №142, прямо противоположно этому.

Я поставил PR, чтобы восстановить 404 как обычные сетевые ошибки, чтобы совпасть с хорошими практиками REST API: https://github.com/apollographql/apollo-link-rest/pull/283

@christrude, хотя я не могу не согласиться с вами в том, что касается REST API, цель этой библиотеки - заставить REST API работать как GraphQL. Следовательно, если подход GraphQL к отсутствующим ресурсам должен возвращать null , тогда эта библиотека должна преобразовать соглашение RESTful 404 в соглашение о возвращаемом значении GraphQL null .

@christrude, хотя я не могу не согласиться с вами в том, что касается REST API, цель этой библиотеки - заставить REST API работать как GraphQL. Следовательно, если подход GraphQL к отсутствующим ресурсам должен возвращать null , тогда эта библиотека должна преобразовать соглашение RESTful 404 в соглашение о возвращаемом значении GraphQL null .

Тогда как GraphQL предлагает вам обрабатывать ответ 404 в пользовательском интерфейсе? Ничего не делать? Значит, запросы просто тихонько умирают? Это невероятно плохое / плохое управление UX / api.

Если вы запрашиваете элемент по идентификатору и получаете обратно null, обработайте это соответствующим образом в пользовательском интерфейсе. Если он содержит данные, отобразите его.

Я согласен с @marnusw здесь, мы не можем реально контролировать, что делает пользовательский API отдыха, поэтому библиотека не должна быть чрезмерно ограничительной в том, что она позволяет. Отображение 404 => null - это относительно интуитивно понятная семантика, которая позволяет вам перейти от модели REST с одним ресурсом на запрос к модели с несколькими ресурсами на запрос (с точки зрения клиента) GraphQL, не увеличивая при этом недостающие данные.

Возможно, есть лучший способ отказаться от этого поведения, например, предварительно упакованная версия преобразователя ответов или абстракция логики обработки запросов, которая позволяет пользователю полностью контролировать обработку статуса http. Но я не думаю, что возвращение к предыдущему поведению - правильный подход.

Отчасти проблема этого подхода заключается в том, что в подписке на результат вы не знаете, является ли это нулевым результатом, потому что это 404, или это возврат 201 без содержимого или что-то подобное. Я исправил это в Afterware, проверяя статус и заставляя его выдавать ошибку, предполагающую проблему, потому что я не могу получить доступ к фактическому сообщению об ошибке сервера, особенно в моем случае, потому что мы используем пользовательскую выборку для ввода токена аутентификации , и не может использовать его для получения ответа до того, как apollo удалит его. Мое решение - плохое одеяло для других ответов 404 в приложении, за исключением одного случая.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги