最近,我的任务是使用较新的@apollo/服务器软件包升级较旧版本的Apollo-Server-express。 Apollo-Server-Express今年即将到来,我们想利用Apollo在过去两年中引入的所有新功能。虽然升级涉及几个差异,但一种特殊的更改引起了我们的注意 - 取消了我们在应用程序中广泛使用的自定义错误类别的支持。我们面临的挑战是找到一个解决方案,该解决方案使我们能够无缝过渡到新版本而不会破坏现有用户。
在上一个版本中,我们处理未经授权的访问非常类似于以下代码段:
if (!hasAccess) {
// Removed!
throw new ForbiddenError("You don't have access");
}
apollo upgrade docs的建议是用GraphQLError
替换这些实例,就像:
if (!hasAccess) {
throw new GraphQLError("You don't have access", extensions: { code: 'FORBIDDEN' });
}
尽管这从技术上解决了我们的问题,但在我们所有的旧错误中添加 extensions
属性感到很麻烦。但是,我们发现了一个受阿波罗以前的方法启发的简单而优雅的解决方案:扩展 GraphQLError
创建我们自己的自定义错误。
为了实现此目的,我们定义了自定义错误类,如下所示:
export class AuthenticationError extends GraphQLError {
constructor(message: string) {
super(message, {
extensions: {
code: 'UNAUTHENTICATED',
http: {
status: 401,
},
},
});
}
}
export class ForbiddenError extends GraphQLError {
constructor(message: string) {
super(message, {
extensions: {
code: 'FORBIDDEN',
http: {
status: 403,
},
},
});
}
}
创建自己的自定义错误使我们能够将设置和发送extensions
封装在一个地方,这确保我们与对这些错误的响应方式保持一致。作为额外的奖励,它在丢弃适当错误时,有机会发送401或403状态代码,这是我们的一些客户要求的。
这将很多工作都变成了一条非常直接的升级路径。通过简单地更新导入,我们可以在保持相同功能的同时解决大多数问题。这意味着我们API的消费者无需进行任何更改以适应我们的系统,从而确保过渡顺利。