AWS CDK部署报错:指定的API标识符无效问题解决
问题:AWS CDK为已有API Gateway REST API添加路由集成时部署失败
问题场景
尝试通过AWS CDK为已有的API Gateway REST API添加新的路由和集成,使用的代码如下:
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; export interface IApiGatewayIntegrationProps extends cdk.StackProps { /** * Application Name. Will be used to name all the resources */ appName: string; /** * Route name to add the API Gateway Integration onto. * For example: setting `admin` for admin-api, the invocation url will be `${apiGatewayInvocationUrl}/admin` */ apiPath: string; /** * REST API ID for an existing API */ restApiId: string; /** * ID for the root resource in the API */ restApiRootResourceId: string; /** * VPC Link ID */ VpcLink: string; /** * URL for the Network Load Balancer (NLB) */ NLBDns: string; /** * Listener port on the NLB */ NLBPort: number; } export class CustomApiGatewayIntegration extends Construct { constructor(scope: Construct, id: string, props: IApiGatewayIntegrationProps) { super(scope, id); const api = cdk.aws_apigateway.RestApi.fromRestApiAttributes(scope, 'api', { restApiId: props.restApiId, rootResourceId: props.restApiRootResourceId, }); const proxyIntegration = new cdk.aws_apigatewayv2.CfnIntegration(this, 'gateway-integration', { apiId: api.restApiId, connectionId: props.VpcLink, connectionType: 'VPC_LINK', description: 'API Integration', integrationMethod: 'ANY', integrationType: 'HTTP_PROXY', integrationUri: `http://${props.NLBDns}:${props.NLBPort}/${props.apiPath}/{proxy}`, }); new cdk.aws_apigatewayv2.CfnRoute(this, 'gateway-route', { apiId: api.restApiId, routeKey: 'ANY somepath/{proxy+}', target: `integrations/${proxyIntegration.ref}`, }); } }
部署CDK栈后,终端及CloudFormation控制台均出现以下错误:
failed: Error: The stack named $STACK_NAME failed to deploy: UPDATE_ROLLBACK_COMPLETE: Invalid API identifier specified $AWS_ACCOUNT_ID:$REST_API_ID
错误信息中除实际API ID外还包含AWS账号ID,需解决此问题。
补充背景
AWS CloudFormation有两个API Gateway资源组:
AWS::APIGateway:对应REST API v1类型AWS::APIGatewayV2:对应HTTP API、WebSocket API等v2类型
旧版AWS CDK(v1.x)需分别导入两类资源:
// 旧版导入v1资源 import * as apigateway from '@aws-cdk/aws-api-gateway'; // 旧版导入v2资源 import * as apigatewayv2 from '@aws-cdk/aws-api-gatewayv2';
新版CDK(v2+)已整合相关资源,调用方式如下:
import * as cdk from 'aws-cdk-lib'; // 调用v1资源组 const api = new cdk.aws_apigateway.RestApi(...); // 调用v2资源组 const apiv2 = new cdk.aws_apigatewayv2.CfnRestApi(...);
问题原因及解决方法
核心原因
代码混用了API Gateway v1和v2的资源:
- 通过
cdk.aws_apigateway.RestApi.fromRestApiAttributes导入的是v1的REST API,其ID在CDK中会被格式化为账号ID:API ID的形式 - 但创建集成和路由时使用的是
cdk.aws_apigatewayv2.CfnIntegration和cdk.aws_apigatewayv2.CfnRoute,这些是v2资源组的构造,而v2资源的apiId参数仅接受v2 API的纯ID,因此CloudFormation识别为无效标识符。
修复步骤
将集成和路由的创建改为使用v1资源组的构造,修改后的完整代码如下:
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; export interface IApiGatewayIntegrationProps extends cdk.StackProps { /** * 应用名称,用于命名所有资源 */ appName: string; /** * 要添加集成的API路径,例如设置`admin`后,调用URL为`${apiGatewayInvocationUrl}/admin` */ apiPath: string; /** * 已有REST API的ID */ restApiId: string; /** * API的根资源ID */ restApiRootResourceId: string; /** * VPC Link ID */ VpcLink: string; /** * 网络负载均衡器(NLB)的DNS地址 */ NLBDns: string; /** * NLB的监听端口 */ NLBPort: number; } export class CustomApiGatewayIntegration extends Construct { constructor(scope: Construct, id: string, props: IApiGatewayIntegrationProps) { super(scope, id); const api = cdk.aws_apigateway.RestApi.fromRestApiAttributes(scope, 'api', { restApiId: props.restApiId, rootResourceId: props.restApiRootResourceId, }); // 创建路径资源及代理资源 const apiPathResource = api.root.addResource(props.apiPath); const proxyResource = apiPathResource.addResource('{proxy+}'); // 创建v1的HTTP代理集成 const proxyIntegration = new cdk.aws_apigateway.HttpIntegration('gateway-integration', { url: `http://${props.NLBDns}:${props.NLBPort}/${props.apiPath}/{proxy}`, httpMethod: 'ANY', options: { connectionType: cdk.aws_apigateway.ConnectionType.VPC_LINK, vpcLink: cdk.aws_apigateway.VpcLink.fromVpcLinkId(this, 'ExistingVpcLink', props.VpcLink), }, }); // 为代理资源添加ANY方法(绑定路由) proxyResource.addMethod('ANY', proxyIntegration); } }
关键修改点
- 移除
aws_apigatewayv2相关构造,改用v1的HttpIntegration实现代理集成 - 通过
api.root.addResource逐层创建路径资源和{proxy+}代理资源 - 使用
VpcLink.fromVpcLinkId导入已有VPC Link,适配v1资源的参数要求 - 直接为代理资源添加
ANY方法,v1中方法与路由自动绑定,无需手动创建Route
内容的提问来源于stack exchange,提问作者retr0
相关产品推荐
相关产品推荐

