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


поскольку вы можете видеть, что здесь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)
})
}
}
Хорошо, я пытаюсь это сделать, но не могу понять, как связать эту штуку с Аполлоном. Есть ли у нас какой-либо пример кода, который указывает, как их соединить вместе, или автор может предоставить пример? Спасибо.
Для 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
}
})})
Недооцененный ответ