When trying to use aws-apigatewayv2/CfnIntegration in order to create an HTTP API Gateway that forwards traffic across a VPC Link (v2) to an internal ALB, it fails. If I use the AWS UI to manually create an integration for the HTTP API Gateway created in the stack, I can use the same VPC Link and Application Load Balancer, and it works fine.
const appLoadBalancer = new elbv2.ApplicationLoadBalancer(this, 'AppLoadBalancer', {
vpc: myvpc,
loadBalancerName:"Test-ALB",
internetFacing: false,
});
const appListener = appLoadBalancer.addListener('AppLoadBalancerListener', {
port: 80,
protocol: ApplicationProtocol.HTTP
});
const appTargetGroup = appListener.addTargets('AppLoadBalancerListenerTarget', {
targetGroupName: "Test-ALB-Target-Group",
port: 80,
targets: [],
deregistrationDelay: Duration.seconds(30)
});
const httpVpcLink = new cdk.CfnResource(this, "HttpVpcLink", {
type: "AWS::ApiGatewayV2::VpcLink",
properties: {
Name: "V2 VPC Link",
SubnetIds: "insert real subnet id here"
}
});
const httpApiGateway2 = new HttpApi(this, "HttpApiGateway", {
createDefaultStage: false
});
const httpApiGatewayIntegration = new CfnIntegration(this, "HttpApiGatewayIntegration", {
apiId: httpApiGateway2.httpApiId,
connectionId: httpVpcLink.ref,
connectionType: "VPC_LINK",
description: "API Integration",
integrationMethod: "ANY",
integrationType: "HTTP_PROXY",
integrationUri: appLoadBalancer.loadBalancerArn,
payloadFormatVersion: "1.0",
});
I've also tried explicitly putting in the ARN of the load balancer in the integrationUri, and that fails with the same error (i.e.:
integrationUri: "arn:aws:elasticloadbalancing:us-east-1:....:loadbalancer/app/Test-ALB/...72d925").
(I commented out the CfnIntegration creation, and created the stack, so I could manually try creating the integration in the UI [which works] and to try putting in the actual ARN in the CDK typescript, which doesn't work).
I've tried with a network load balancer as well, and it also fails with the same error.
It creates the cloudformation stack and then fails with:
For VpcLink V2, integration uri should be a valid ELB Listener ARN or a valid CloudMap service ARN. (Service: AmazonApiGatewayV2; Status Code: 400; Error Code: BadRequestException; Request ID: 3426bf33-472c-4523-8df5-c99f40c7178d)
This is :bug: Bug Report
@GregThoen
integrationUri should point to the listenerArn not the loadBalancerArn.
Considering the sample below the API Gateway HTTP API VpcLink integration will route to the internal ALB for Fargate Service.
import * as cdk from '@aws-cdk/core';
import * as apig from '@aws-cdk/aws-apigatewayv2';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as ecsPatterns from '@aws-cdk/aws-ecs-patterns';
import * as ecs from '@aws-cdk/aws-ecs';
export class ApigStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = this.node.tryGetContext('use_default_vpc') === '1' ?
ec2.Vpc.fromLookup(this, 'Vpc', { isDefault: true }) :
this.node.tryGetContext('use_vpc_id') ?
ec2.Vpc.fromLookup(this, 'Vpc', { vpcId: this.node.tryGetContext('use_vpc_id') }) :
new ec2.Vpc(this, 'Vpc', { maxAzs: 3, natGateways: 1 });
const svc = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'FargateSvc', {
vpc,
publicLoadBalancer: false,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('pahud/amazon-ecs-flask-sample'),
environment: {
PLATFORM: 'FARGATE with API Gateway'
}
}
})
const httpVpcLink = new cdk.CfnResource(this, "HttpVpcLink", {
type: "AWS::ApiGatewayV2::VpcLink",
properties: {
Name: "V2 VPC Link",
SubnetIds: vpc.privateSubnets.map(m => m.subnetId)
}
});
const api = new apig.HttpApi(this, "HttpApiGateway", {
createDefaultStage: true
});
const integration = new apig.CfnIntegration(this, "HttpApiGatewayIntegration", {
apiId: api.httpApiId,
connectionId: httpVpcLink.ref,
connectionType: "VPC_LINK",
description: "API Integration",
integrationMethod: "ANY",
integrationType: "HTTP_PROXY",
integrationUri: svc.listener.listenerArn,
payloadFormatVersion: "1.0",
});
new apig.CfnRoute(this, 'Route', {
apiId: api.httpApiId,
routeKey: 'ANY /{proxy+}',
target: `integrations/${integration.ref}`,
})
new cdk.CfnOutput(this, 'APIUrl', { value: api.url! })
}
}
When you open the API Gateway URL you should see this welcome page.

I'm so sorry I didn't notice that! Thank you for the prompt reply and helping!
@GregThoen No worries. I will be happy to build the L2 to simplify it. Thanks for bringing it up.
Most helpful comment
@GregThoen
integrationUrishould point to the listenerArn not the loadBalancerArn.Considering the sample below the API Gateway HTTP API VpcLink integration will route to the internal ALB for Fargate Service.
When you open the API Gateway URL you should see this welcome page.