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

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

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

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 даже для неудачных запросов / мутаций, или я могу как-нибудь обновить код состояния объектов ответа? Если нет, как мне установить вышеупомянутый код состояния объекта ошибки?


person Stretch0    schedule 20.04.2018    source источник


Ответы (4)


Если сам запрос 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)
    })
  }
}
person Daniel Rearden    schedule 21.04.2018
comment
Недооцененный ответ - person Dimitar Nikovski; 17.10.2018
comment
Хорошо, я пытаюсь это сделать, но не могу понять, как связать эту штуку с Аполлоном. Есть ли у нас какой-нибудь пример кода, который указывает, как соединить их вместе, или автор может предоставить пример? Спасибо. - person lloydaf; 16.09.2019

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

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

person Uziel Valdez    schedule 20.04.2018

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

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

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

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

Дополнительную информацию по этой теме см. В этом блоге

person larsivi    schedule 27.12.2019

Попробуйте добавить ответ и установить такой код состояния ответа, предполагая, что ваш 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
}
})})
person Kuramochi-coder    schedule 17.02.2021