Перенаправление GraphQL, когда преобразователь выдает ошибку

Я использую graphql-server-express для создания сервера GraphQL, который использует REST API.

Я нахожусь в ситуации, когда вызов REST может возвращать код состояния 301 или 401, когда пользователь не аутентифицирован для доступа к ресурсу. Я использую файл cookie, который устанавливается на клиенте и пересылается в REST API при разрешении запроса GraphQL.

Можно ли отправить клиенту перенаправление 301 в ответ на вызов конечной точки GraphQL при возникновении такой ошибки?

Я пробовал что-то вроде res.sendStatus(301) … в formatError, но это не работает, поскольку graphql-server-express пытается установить заголовки после этого.

Я также попытался замкнуть промежуточное ПО graphqlExpress чем-то вроде этого:

export default graphqlExpress((req, res) => {
  res.sendStatus(301);
  return;
});

Хотя клиент получает правильный результат, сервер по-прежнему выводит ошибки (в данном случае TypeError: Cannot read property 'formatError' of undefined - скорее всего, потому, что промежуточное ПО получает пустые параметры).

Есть ли хороший способ заставить это работать? Спасибо!


person amann    schedule 22.12.2016    source источник
comment
Перенаправить куда? Перенаправление в GraphQL на самом деле не имеет смысла. Что, если клиент отправляет запрос с двумя корневыми узлами, один успешно (не требуется вход в систему), а другой не работает, что вы отправляете, 300 или 200?   -  person Ruslan Talpa    schedule 22.12.2016
comment
Если хотя бы одно поле выходит из строя, в моем случае должно быть отправлено перенаправление.   -  person amann    schedule 23.12.2016
comment
Но запросы graphql выполняются JS-кодом, а не браузером напрямую, но отправка перенаправления не означает, что браузер загрузит страницу входа. Вашему клиенту graphql необходимо обнаружить этот код ответа, а затем жестко запрограммировать его, чтобы что-то сделать, когда это произойдет.   -  person Ruslan Talpa    schedule 23.12.2016
comment
Лучше просто отправить ту же информацию в свой ответ об ошибке json, и ваш клиент отреагирует на нее. Смена кода ответа вам совершенно не помогает.   -  person Ruslan Talpa    schedule 23.12.2016
comment
Вы правы. Я почему-то думал, что код состояния 301 заставит клиента изменить его местоположение, но, например, fetch просто следует за перенаправлением и загрузит этот ресурс. Так что, вероятно, лучший способ - это, как вы упомянули, генерировать пользовательскую ошибку перенаправления в моем преобразователе, которую клиент знает, как обрабатывать - возможно, с помощью apollo client afterware (в связанном примере они фактически используют код состояния ответа для реакции на выход из системы)   -  person amann    schedule 23.12.2016


Ответы (2)


Вот как я это реализовал.

На стороне сервера:

// Setup
export default class UnauthorizedError extends Error {
  constructor({statusCode = 401, url}) {
    super('Unauthorized request to ' + url);
    this.statusCode = statusCode;
  }
}

// In a resolver
throw new UnauthorizedError({url});

// Setup of the request handler
graphqlExpress(async (req, res) => ({
  schema: ...,
  formatError(error) {
    if (error.originalError instanceof UnauthorizedError) {
      res.status(error.originalError.statusCode);
      res.set('Location', 'http://domain.tld/login');
    } else {
      res.status(500);
    }

    return error;
  },
});

На стороне клиента:

const networkInterface = createNetworkInterface();

networkInterface.useAfter([{
  applyAfterware({response}, next) {
    if ([401, 403].includes(response.status)) {
      document.location = response.headers.get('Location');
    } else {
      next();
    }
  }
}]);

В Apollo Client 2.0 вы, вероятно, можете использовать apollo-link- ошибка на стороне клиента для этого.

person amann    schedule 18.12.2017

Другой способ обработки перенаправлений в преобразователях graphql - установить статус 302 (код статуса http для перенаправления) и Location в ответе, как показано ниже,

this.Query = {
  downloadFile: (parent, { url }, { res }) => {
    res.status(302);
    res.set('Location', url);

    return;
}
person Shivathanu GC    schedule 20.08.2020