解析器抛出错误时 GraphQL 重定向
GraphQL redirect when resolver throws error
我正在使用 graphql-server-express
构建一个使用 REST API 的 GraphQL 服务器。
我的情况是,当用户未通过身份验证无法访问资源时,REST 调用可能 return 301 或 401 状态代码。我正在使用在客户端上设置并在解析 GraphQL 查询时转发到 REST API 的 cookie。
是否可以在发生此类错误时向客户端发送 301 重定向以响应对 GraphQL 端点的调用?
我在 formatError
中尝试过类似 res.sendStatus(301) …
的方法,但这效果不佳,因为 graphql-server-express
试图在此之后设置 headers。
我也试过 short-circuit graphqlExpress
中间件,像这样:
export default graphqlExpress((req, res) => {
res.sendStatus(301);
return;
});
虽然客户端收到正确的结果,但服务器仍然打印错误(在这种情况下 TypeError: Cannot read property 'formatError' of undefined
– 很可能是因为中间件收到空选项)。
有什么好的方法可以让它发挥作用吗?谢谢!
我是这样实现的。
在服务器端:
// 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-error。
在 graphql 解析器中处理重定向的另一种方法是将“status”设置为 302(重定向的 http 状态代码)和响应中的“Location”,如下面的代码,
this.Query = {
downloadFile: (parent, { url }, { res }) => {
res.status(302);
res.set('Location', url);
return;
}
我正在使用 graphql-server-express
构建一个使用 REST API 的 GraphQL 服务器。
我的情况是,当用户未通过身份验证无法访问资源时,REST 调用可能 return 301 或 401 状态代码。我正在使用在客户端上设置并在解析 GraphQL 查询时转发到 REST API 的 cookie。
是否可以在发生此类错误时向客户端发送 301 重定向以响应对 GraphQL 端点的调用?
我在 formatError
中尝试过类似 res.sendStatus(301) …
的方法,但这效果不佳,因为 graphql-server-express
试图在此之后设置 headers。
我也试过 short-circuit graphqlExpress
中间件,像这样:
export default graphqlExpress((req, res) => {
res.sendStatus(301);
return;
});
虽然客户端收到正确的结果,但服务器仍然打印错误(在这种情况下 TypeError: Cannot read property 'formatError' of undefined
– 很可能是因为中间件收到空选项)。
有什么好的方法可以让它发挥作用吗?谢谢!
我是这样实现的。
在服务器端:
// 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-error。
在 graphql 解析器中处理重定向的另一种方法是将“status”设置为 302(重定向的 http 状态代码)和响应中的“Location”,如下面的代码,
this.Query = {
downloadFile: (parent, { url }, { res }) => {
res.status(302);
res.set('Location', url);
return;
}