如何在 AWS 上重命名 API 网关路径参数
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
在 AWS API Gateway 中重命名路径参数可能是一项复杂的任务,无论您使用的是基于 aws-apigateway (v1) 模块的 REST API,还是基于 aws-apigateway v2 (v2) 模块的 HTTP API。本文将探讨这两个模块中重命名路径参数的过程,并讨论两种解决方案,以在不影响用户体验的前提下实现所需结果。
REST API 代码(v1)
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
const getArticle = new lambda.Function(this, 'GetArticle', {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('path/to/getArticle/code'),
});
const restApi = new apigateway.RestApi(this, 'MyRestApi');
restApi.root
.resourceForPath('/get-article/{id}')
.addMethod('GET', new apigateway.LambdaIntegration(getArticle));
HTTP API 代码(v2)
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigatewayv2 from 'aws-cdk-lib/aws-apigatewayv2';
import * as integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';
const getArticle = new lambda.Function(this, 'GetArticle', {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('path/to/getArticle/code'),
});
const httpApi = new apigatewayv2.HttpApi(this, 'MyHttpApi');
httpApi.addRoutes({
path: '/get-article/{id}',
methods: ['GET'],
integration: new integrations.LambdaProxyIntegration({
handler: getArticle,
}),
});
假设您需要检索一篇文章,不仅要根据文章的 URL id,还要根据文章与新闻简报的关联性进行检索。在这种情况下,您需要将端点路径从 ` /get-article/{id}<article_name>`修改为 `<newsletters_name>`。虽然这种更改纯粹是语义上的,但您可以将 ` <article_name> /get-article/{newsletterId}/{articleId}` 的值赋给 ` <newsletters_name>`,并引入一个名为 `<newsletters_name>` 的新参数。idnewsletterIdarticleId
为了简化问题,我们重点关注将参数重命名id为articleId.
然而,实施此更新并不像乍看起来那么简单。当您尝试使用 部署更改时npx cdk deploy,会遇到以下错误消息:
- 适用于 REST API (v1)
Resource handler returned message: "A sibling ({id}) of this resource already has a variable path part -- only one is allowed (Service: ApiGateway, Status Code: 400, ...
- 适用于 HTTP API (v2)
Resource handler returned message: "The provided route key "GET /get-article/{articleId}" has a conflicting variable on the same hierarchical level as "GET /get-article/{id}" (Service:
AmazonApiGatewayV2; Status Code: 409; Error Code: ConflictException;
重命名 API 路径参数主要有两种解决方案。
方案一:注释、部署、更新和重新部署
优点:简单易行,易于实施。
缺点:如果在生产环境中使用该路由,则需要维护窗口,并且会造成用户停机。
- 注释掉包含旧路径参数的 API 资源。
// restApi.root
// .resourceForPath('/get-article/{id}')
// .addMethod('GET', new apigateway.LambdaIntegration(getArticle));
- 使用以下命令部署更改
npx cdk deploy。 - 取消注释之前注释的代码,并将路径参数名称从 修改
id为articleId。
restApi.root
.resourceForPath('/get-article/{articleId}')
.addMethod('GET', new apigateway.LambdaIntegration(getArticle));
- 使用以下命令再次部署更改
npx cdk deploy。
通过这种方法,您可以有效地更新路径参数,而无需直接重命名。但是,请注意这可能会在部署期间造成停机时间。
注意:另一种方法是从 AWS 控制台手动删除相应的资源。虽然这种方法在某些情况下可能有效,但由于它可能给 CDK 堆栈带来潜在的复杂性,因此不建议使用。
方案二:创建并迁移到新资源
优点:用户无需等待。
缺点:需要暂时维护两个资源,并且需要更新客户端代码才能从旧资源迁移到新资源。
要使用此方法重命名路径参数,请按照以下步骤操作:
- 创建一个新的资源,使用新的路径,但保持与旧资源相同的集成和方法。(例如,
/get-article/v2/{articleId})。
restApi.root
.resourceForPath('/get-article/{id}')
.addMethod('GET', new apigateway.LambdaIntegration(getArticle));
// Add a new resource with the new path parameter name
restApi.root
.resourceForPath('/get-article/v2/{articleId}')
.addMethod('GET', new apigateway.LambdaIntegration(getArticle));
- 通过更新客户端代码以使用新的路径参数名称,将旧资源迁移到新资源。迁移完成后,即可安全地删除旧资源。
- (可选)将新资源重命名为与旧资源名称相同,但路径参数名称要更新为新名称(
/get-article/{articleId})。确保客户端代码也相应更新。
// Remove these lines
// restApi.root
// .resourceForPath('/get-article/{id}')
// .addMethod('GET', new apigateway.LambdaIntegration(getArticle));
restApi.root
// Remove the `/v2` suffix
.resourceForPath('/get-article/{articleId}')
.addMethod('GET', new apigateway.LambdaIntegration(getArticle));
此方案可确保用户获得不间断的服务。但是,它需要暂时管理两台服务器,并协调迁移过程与客户端更新。
结论
按照这些步骤,您可以成功重命名 AWS API 网关中的路径参数。
由于第二种方案的稳健性以及避免用户停机的优势,我们强烈推荐使用。但是,如果您时间紧迫或生产环境没有活跃用户,第一种方案也是一个可行的选择。