Как установить код статуса http в GraphQL

Я хочу установить код состояния http в моем запросе аутентификации GraphQL в зависимости от того, была ли попытка аутентификации успешной (200), неавторизованной (401) или отсутствующими параметрами (422).

Я использую Коа и Аполлон и настроил свой сервер следующим образом:

const graphqlKoaMiddleware = graphqlKoa(ctx => {
  return ({
    schema,
    formatError: (err) => ({ message: err.message, status: err.status }),
    context: {
      stationConnector: new StationConnector(),
      passengerTypeConnector: new PassengerTypeConnector(),
      authConnector: new AuthConnector(),
      cookies: ctx.cookies
    }
  })
})

router.post("/graphql", graphqlKoaMiddleware)

Как видите, я настроил свой formatError так, чтобы он возвращал сообщение и статус, но в настоящее время возвращается только сообщение. Сообщение об ошибке возникает из-за ошибки, которую я бросаю в свою функцию распознавателя.

Например:

const resolvers = {
  Query: {
    me: async (obj, {username, password}, ctx) => {
      try {
        return await ctx.authConnector.getUser(ctx.cookies)  
      }catch(err){
        throw new Error(`Could not get user: ${err}`);
      }
    }
  }
}

Моя единственная проблема с этим методом заключается в том, что он устанавливает код состояния в сообщении об ошибке, а не фактически обновляет объект ответа.

Требуется ли GraphQL ответ 200 даже для неудачных запросов / мутаций, или я могу как-то обновить код состояния объектов ответа? Если нет, как мне установить вышеупомянутый код состояния объекта ошибки?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
2
0
4 837
4

Ответы 4

поскольку вы можете видеть, что здесьformatError не поддерживает код состояния, вы можете создать тип ответа о состоянии с полями сообщения и состояния и вернуть соответствующий ответ на свой преобразователь.

Требует ли GraphQL ответа 200 даже для неудачных запросов / мутаций? Нет, если запрос не удастся, он вернет null и ошибку, которую вы выбросите на стороне сервера.

Если сам запрос GraphQL не имеет неправильной формы, GraphQL вернет код состояния 200, даже если в одном из преобразователей возникнет ошибка. Это сделано намеренно, поэтому на самом деле нет способа настроить сервер Apollo для изменения этого поведения.

Тем не менее, вы можете легко подключить собственное промежуточное ПО. Вы можете импортировать функцию runHttpQuery, которую промежуточное ПО Apollo использует под капотом. Фактически, вы можете практически скопировать исходный код и просто изменить его в соответствии со своими потребностями:

const graphqlMiddleware = options => {
  return (req, res, next) => {
    runHttpQuery([req, res], {
      method: req.method,
      options: options,
      query: req.method === 'POST' ? req.body : req.query,
    }).then((gqlResponse) => {
      res.setHeader('Content-Type', 'application/json')

      // parse the response for errors and set status code if needed

      res.write(gqlResponse)
      res.end()
      next()
    }, (error) => {
      if ( 'HttpQueryError' !== error.name ) {
        return next(error)
      }

      if ( error.headers ) {
        Object.keys(error.headers).forEach((header) => {
          res.setHeader(header, error.headers[header])
        })
      }

      res.statusCode = error.statusCode
      res.write(error.message)
      res.end()
      next(false)
    })
  }
}

Недооцененный ответ

Dimitar Nikovski 17.10.2018 18:08

Хорошо, я пытаюсь это сделать, но не могу понять, как связать эту штуку с Аполлоном. Есть ли у нас какой-либо пример кода, который указывает, как их соединить вместе, или автор может предоставить пример? Спасибо.

lloydaf 16.09.2019 18:40

Для apollo-server установите пакет apollo-server-errors. В случае ошибок аутентификации

import { AuthenticationError } from "apollo-server-errors";

Затем в вашем резольвере throw new AuthenticationError('unknown user');

Это вернет код состояния 400.

Подробнее об этой теме читайте в этот блог

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

const graphqlKoaMiddleware = graphqlKoa(ctx => {
return ({
schema,
response: request.resonse,
formatError: (err) => {
response.statusCode =  err.status;
return ({message: err.message, status: err.status})},
context: {
  stationConnector: new StationConnector(),
  passengerTypeConnector: new PassengerTypeConnector(),
  authConnector: new AuthConnector(),
  cookies: ctx.cookies
}
})})

Другие вопросы по теме