我想在我的GraphQL身份验证查询中设置http状态代码,具体取决于身份验证尝试是否成功(200),未授权(401)或缺少参数(422)。
我正在使用Koa and 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
响应?或者我可以更新响应对象状态代码吗?如果没有,我如何设置上述错误对象状态代码?
答案 0 :(得分:4)
除非GraphQL请求本身格式错误,否则GraphQL将返回200状态代码,即使其中一个解析器中出现错误也是如此。这是设计使得配置Apollo服务器以改变这种行为并不是真正的方法。
也就是说,您可以轻松连接自己的中间件。您可以导入Apollo中间件在引擎盖下使用的runHttpQuery
函数。事实上,你几乎可以复制source code并只是修改它以满足你的需要:
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)
})
}
}
答案 1 :(得分:1)
正如您所看到的那样here formatError
不支持状态代码,您可以创建一个包含消息和状态字段的状态响应类型,并返回解析器上的相应内容。
即使查询/突变失败,GraphQL还是需要200响应吗?
不,如果查询失败,它将返回null
以及您在服务器端抛出的错误。
答案 2 :(得分:0)
对于apollo服务器,请安装apollo-server-errors软件包。对于身份验证错误,
import { AuthenticationError } from "apollo-server-errors";
然后,在您的解析器中
throw new AuthenticationError('unknown user');
这将返回400状态代码。
中了解有关此主题的更多信息答案 3 :(得分:0)
尝试添加响应并设置响应状态代码,假设您的 err.status 已经是一个整数,如 401 等:
td