Apollo-link-rest: Обработка ответа об ошибке

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

Здравствуйте, у меня есть этот API входа, который принимает тело запроса как:

{
    "authentications": {
        "emailAddress": "[email protected]",
        "password": "11111111"
    }
}

Сервер возвращает токен в случае успеха:

{
    "authentications": {
        "token": "eyJhbGoiU3RvcmUifV0sImNyZWF0ZWRBdCI6IjIwMTgtMDktMTZUMTg6NTA6NTYuNT"
    }
}

Если адрес электронной почты или пароль введены неверно, он вернет:

{
    "message": "Cannot find document for class 'User'. searched with parameters: '{\"emailAddress\":\"[email protected]\"}'",
    "errorCode": 1103,
    "status": 404
}

Я могу успешно войти в систему с такой схемой GraphQL:

gql`
  fragment Authentications on any {
    emailAddress: String
    password: String
  }

  fragment AuthInput on REST {
    authentications {
      Authentications
    }
  }

  mutation signIn($input: AuthInput!) {
    authPayload(input: $input) 
      @rest(type: "AuthPayload", path: "/api/v1/authentications", endpoint:"UsersService", method:"POST") {
      authentications @type(name:"Auth"){
        token
      }
    }
  }
`;

У меня вопрос, как я могу получить ответ в случае ошибки (неправильный адрес электронной почты / пароль)? Потому что прямо сейчас, если сервер возвращает ошибку, ответ всегда будет нулевым:

Object {
    "data": Object {
        "authPayload": null,
    },
    "errors": undefined,
}
help wanted 🛠 question❔

Самый полезный комментарий

Я тоже застрял в этом вопросе. Есть ли причина не возвращать полный ответ 404 вместо нуля?

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

Если вы не можете отловить ошибку 400+, думаю, этот выпуск будет вам полезен.
https://github.com/apollographql/apollo-link-rest/issues/151

К вашему сведению: для неправильных учетных данных вы должны вернуть 401.
https://stackoverflow.com/questions/1959947/whats-an-appistent-http-status-code-to-return-by-a-rest-api-service-for-a-val

Всем привет,

Я только что столкнулся с этим, и мне тоже интересно, каков рекомендуемый способ обработки 404. Например, он не запускает apollo-link-error .

Пока что я подумываю написать ссылку на пользовательский обработчик ошибок или проверить содержание данных в ответе в каждом компоненте <Query /> .

FWIW У меня есть тот же случай, когда сервер возвращает, например, 404 вместо 401, но, к сожалению, изменение сервера не является вариантом на данный момент.

Я думаю, что стоит рассмотреть этот вариант использования, потому что коды состояния для REST очень разные - и более разнообразны и важны - чем коды из GraphQL.

Я тоже застрял в этом вопросе. Есть ли причина не возвращать полный ответ 404 вместо нуля?

Мне еще не приходилось сталкиваться со случаем, когда мне помогло не рассмотрение ошибки 404 как ошибки, я все время пытаюсь найти хороший способ обойти этот факт.

Может ли мысль, что 404 Not found описать запрос данных, который успешно, правильно дает пустой набор?

Это также может сигнализировать о том, что владельцы службы внесли такое критическое изменение, что ранее доступная конечная точка исчезла.

Я думаю, что первый случай может быть лучше обработан 200 OK вместе с пустым или нулевым объектом приложения. По крайней мере, кажется, что эти два случая должны быть легко различимы клиентом, поскольку они очень разные.

Да, намеренно пустые наборы данных встречаются немного чаще, чем можно было бы подумать? (По крайней мере, я был удивлен!) Поскольку пользователи часто собирают несколько сетевых и других вызовов в один мета-вызов, по умолчанию выдача ошибки на 404 имеет огромное влияние, потому что один 404 прервет все другие выборки данных, которые происходят параллельно. Я согласен, если бы был только один вызов REST на каждый выполненный запрос GraphQL, мне казалось, что мы должны выдать ошибку с учетом официальной семантики REST.

На практике лучше не выдавать ошибку по умолчанию! Поскольку вы можете обойти это, добавив настраиваемую выборку, и это похоже на «будьте либеральны в том, что вы принимаете»; казалось, что этот выбор соответствует одной из ключевых целей Apollo-link-rest: помогать пользователям, которые не обязательно контролируют бэкэнд, а существует много серверов только «в основном REST», поэтому семантические нарушения являются обычным явлением. .

@williamboman относительно просто настроить Apollo-link-rest для выдачи 404, если вы используете параметр customFetch Я не на своем компьютере, но дайте мне знать, если вам понадобится помощь в этом!

Привет, @fbartho, пожалуйста , помогите мне с написанием customFetch для обработки ошибок 404? Есть какой-нибудь пример?

@anasnain :

В javascript это будет выглядеть примерно так:

export async function customFetch(requestInfo, init) {
  const response = await fetch(requestInfo, init);
  if (response.status === 404) {
    throw new Error("404 File Not Found"); // Customize this however you like!
  }
  return response;
}

(В TypeScript это было бы немного более подробно)

@fbartho Спасибо за быстрый ответ. Теперь я могу поймать 404.
Но как мне убедиться, что networkError или apollo-link-error перехватывает ошибку (генерирует новую ошибку («404 File Not Found»)), записанную внутри пользовательской выборки?

К сожалению, я думаю, что он будет отображаться прикрепленным к массиву graphQLErrors (а не к свойству networkError ) из-за внутренних правил ApolloClient (о том, как работают ссылки).

Возможно, это поправимо, но я не знаю, как это сделать. - HTTPLink должен знать, как это делать, а у меня не было возможности разобраться. В нашей (рабочей) кодовой базе есть вспомогательный метод, который просто распаковывает вложенные ошибки. (Это также было необходимо для ошибок, возникших из apollo-link-state для нас, поэтому на самом деле это не было приоритетом)

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

@anasnain Я так давно не настраивал, что забыл.

Вам также необходимо настроить экземпляр apollo-link-error, это моя конфигурация:

const attachGQLErrorsToNetworkError = (
    graphQLErrors: readonly GraphQLError[],
    networkError: Error,
): void => {
    (networkError as any).tr_graphQLErrors = graphQLErrors;
    return;
};

/** Set behavior when errors occur and handle our own TR errors */
export const apolloErrorLink = onError((errorResponse: ErrorResponse) => {
    const {
        graphQLErrors = [],
        networkError,
    }: {
        graphQLErrors?: readonly GraphQLError[];
        networkError?: Error;
    } = errorResponse;

    /**
     * Our error parsing (function recursiveGQLErrorsFromNetworkError) rely
     * on attaching the following graphql errors.
     * Let's make sure to not attach anything `wrong` (ie: null, empty, ...)
     */
    const hasGraphQLErrors: boolean =
        graphQLErrors != null &&
        Array.isArray(graphQLErrors) &&
        graphQLErrors.length > 0;

    if (networkError && hasGraphQLErrors) {
        /*
         * graphQLErrors are not being passed through the chain of links,
         * but network errors are attaching the graphQLErrors to networkError
         * to be able to access them in a component
         */
        attachGQLErrorsToNetworkError(graphQLErrors, networkError);
    }
});

После дальнейшего размышления: я не совсем уверен, что понимаю ситуацию, которую вы описываете.

Проблема в том, что вы не можете прочитать «ошибку 404» в коде вашего компонента / реакции?

@fbartho
Сценарий: я выполняю запрос ниже rest API и ожидаю, что я должен получить объект ошибки, если он вернет код ошибки 404, как и в случае других ошибок 4xx и ошибок 5xx. но в этом случае ошибка не определена, а данные равны нулю.
const {загрузка, ошибка, данные} = useQuery (CLIENT_API_QUERY);

Это экземпляр клиента Apollo:

async function customFetch(requestInfo, init) {
    const response = await fetch(requestInfo, init);
    if (response.status === 404) {
        response.json().then((errorResponse) => {
          throw new Error(errorResponse);
        });
    }
    return response;
  }

const errorLink = onError(({ operation, response, graphQLErrors, networkError }) => {
    if (graphQLErrors) {
      graphQLErrors.forEach(({ message, path }) =>
           console.log(`[GraphQL error]: Message: ${message}, Path: ${path}`),
      );
    }
    if (networkError) {
        console.log(`[Network error ${operation.operationName}]: ${networkError.message}`);
    }
  });

const restLink = new RestLink({
    uri: 'https://run.mocky.io/v3/df72bacd-39cb-476d-bfda-06d7f5e9d77d',
    customFetch: (requestInfo, init) => customFetch(requestInfo, init)
});

const apolloClient = new ApolloClient({
    link: ApolloLink.from([errorLink, restLink]),
    new InMemoryCache(),
  });
export default apolloClient;

@anasnain - одна вещь, о которой я знаю, это то, что я не думаю, что вы можете передать произвольный объект при выполнении new Error

Кроме того, я думаю, вам не хватает ожидания, поэтому оператор throw выполняется вне вызова restLink customFetch!

const err = new Error("404 Error");
try {
  err.responseJson = await response.json(); // This await crucial to get the error in the right spot!
} catch (parsingError) {
  // figure out what you want to do with parsingError?
}
throw err;
Была ли эта страница полезной?
0 / 5 - 0 рейтинги